如何将来自不同子组件的数据保存到父组件的单一数组中

huangapple go评论64阅读模式
英文:

How to save data from different children to a single array in parent component

问题

以下是您要翻译的内容:

"我有三个组件。每当我在任何子组件(FirstSecond)中点击按钮时,父组件(Test)应该显示输入到子组件的文本。问题是,每当我点击其他子组件的按钮时,都会创建一个新数组,其中包含来自该特定组件的数据。
以下是代码:

Test 组件:

function Test() {
    const [ChildData, setChildData] = useState('');

    console.log(ChildData)

    return (
        <div>
            <h1>Test</h1>
            <div>
                {ChildData ? <div>{ChildData.map((data) => { return <div>{data}</div> })}</div> : null}
            </div>
            <First passChildData={setChildData} />
            <Second passChildData={setChildData} />
        </div>
    )
}

First 组件:

function First(props) {

    const [Data, setData] = useState('');
    const [Items, setItems] = useState('')

    const handlechange = (e) => {
        setData(e.target.value)
    }
    const handleClick = () => {
        if (Data !== '') {
            setItems((prevData) => {
                const newData = [...prevData, Data];
                props.passChildData(newData)
                return newData
            })
            setData('')
        } else {
            console.log("请输入一些内容")
        }
    }

    return (
        <div>
            <h1>First</h1>
            <input type="text" onChange={handlechange} value={Data} />
            <button onClick={handleClick}>添加</button>
            {Data}
            <div>{Items ? <div>{Items.map((item) => { return <div>{item}</div> })}</div> : null }</div>
        </div>
    )
}

Second 组件:

function Second(props) {

    const [Data, setData] = useState('');
    const [Items, setItems] = useState('')

    const handlechange = (e) => {
        setData(e.target.value)
    }
    const handleClick = () => {
        if (Data !== '') {
            setItems((prevData) => {
                const newData = [...prevData, Data];
                props.passChildData(newData)
                return newData
            })
            setData('')
        } else {
            console.log("请输入一些内容")
        }
    }

    return (
        <div>
            <h1>Second</h1>
            <input type="text" onChange={handlechange} value={Data} />
            <button onClick={handleClick}>添加</button>
            {Data}
            <div>{Items ? <div>{Items.map((item) => { return <div>{item}</div> })}</div> : null }</div>
        </div>
    )
}

我期望的是:

  • 当我在First组件中输入“什么”;
  • 然后在Second组件中输入“是”;
  • 然后在First组件中输入“你的”;
  • 然后在Second组件中输入“名字?”

我希望在父组件(Test)内显示“什么是你的名字?”(不管它是否在不同的div或行中;我希望每个项目都按输入的顺序显示)。"

英文:

Here I have three components. Whenever I click the button in any of the child components (First and Second) the parent (Test) component should display text entered into the child component. The problem is that whenever I click the button of other child component a new array is created with data from that particular component.
Here's the code:

Test component:

function Test() {
    const [ChildData , setChildData] = useState(&#39;&#39;);
    
    console.log(ChildData)

  return (
    &lt;div&gt;
        &lt;h1&gt;Test&lt;/h1&gt;
        &lt;div&gt;
            {ChildData? &lt;div&gt;{ChildData.map((data)=&gt;{return &lt;div&gt;{data}&lt;/div&gt; })}&lt;/div&gt;:null }
        &lt;/div&gt;
        &lt;First passChildData={setChildData}/&gt;
        &lt;Second passChildData={setChildData}/&gt;       
    &lt;/div&gt;
  )
}

First component:

function First(props) {

  const [Data, setData] = useState(&#39;&#39;);
  const [Items, setItems] = useState(&#39;&#39;)

  const handlechange = (e)=&gt;{
    setData(e.target.value)
  }
  const handleClick = ()=&gt;{
    if(Data != &#39;&#39;){
      setItems((prevData)=&gt;{
        const newData = [...prevData,Data];
        props.passChildData(newData)
        return newData
      })
      setData(&#39;&#39;)
    }else{
      console.log(&quot;enter something&quot;)
    }
  }

  return (
    &lt;div&gt;
        &lt;h1&gt;First&lt;/h1&gt;
        &lt;input type=&quot;text&quot; onChange={handlechange} value={Data}/&gt;
        &lt;button onClick={handleClick}&gt;Add&lt;/button&gt;
        {Data}
        &lt;div&gt;{Items? &lt;div&gt;{Items.map((item)=&gt;{return &lt;div&gt;{item}&lt;/div&gt; })}&lt;/div&gt;:null }&lt;/div&gt;
    &lt;/div&gt;
  )
}

Second component:

function Second(props) {
  
  const [Data, setData] = useState(&#39;&#39;);
  const [Items, setItems] = useState(&#39;&#39;)

  const handlechange = (e)=&gt;{
    setData(e.target.value)
  }
  const handleClick = ()=&gt;{
    if(Data != &#39;&#39;){
      setItems((prevData)=&gt;{
        const newData = [...prevData,Data];
        props.passChildData(newData)
        return newData
      })
      setData(&#39;&#39;)
    }else{
      console.log(&quot;enter something&quot;)
    }
  }

  return (
    &lt;div&gt;
        &lt;h1&gt;Second&lt;/h1&gt;
        &lt;input type=&quot;text&quot; onChange={handlechange} value={Data}/&gt;
        &lt;button onClick={handleClick}&gt;Add&lt;/button&gt;
        {Data}
        &lt;div&gt;{Items? &lt;div&gt;{Items.map((item)=&gt;{return &lt;div&gt;{item}&lt;/div&gt; })}&lt;/div&gt;:null }&lt;/div&gt;
    &lt;/div&gt;
  )
}

What I expect is:

  • When I enter "What" into the First component;
  • Then "is" into the Second component;
  • Then "your" into the First component
  • Then "name?" in Second component

I want "What is your name?" (Doesn't matter if it's in different divs or lines; I want every single item to be displayed in the order it was entered) to be shown inside the parent (Test) component.

答案1

得分: 1

首先,我不会有两个几乎相同的组件 - FirstSecond - 除了它们的标题之外,我会有一个带有 heading 作为属性的单一组件。

其次,我会使用一个带有 onSubmit 处理程序的 &lt;form&gt;,而不是一个带有 onClick 处理程序的 &lt;button&gt;,因为这样用户可以通过在输入字段具有焦点时按下 [Enter] 键来添加项目,例如。

第三,我会使用 useEffect 钩子来监听对 First 组件到 Items 数组的更改,然后在有更改时调用 passChildData 属性函数。请注意,用于引用数组的变量应该用空数组初始化,例如:const [Items, setItems] = useState([])

最终的代码如下:

英文:

First, I would not have two components - First and Second - that are nearly identical except for their headings; I would have a single component with heading as a prop.

Second, I would use a &lt;form&gt; with an onSubmit handler instead of a &lt;button&gt; with an onClick handler because this will allow the user to add an item by, for example, pressing [Enter] while the input field has focus.

Third, I would use the useEffect hook to listen for changes in the First component to the Items array and then call the passChildData prop function when there is a change. Note that variables that are to reference arrays should be initialized with empty arrays, for example: const [Items, setItems] = useState([]).

The final code looks like:

function Test() {
  const [ChildData, setChildData] = useState([]);

  const setItem = (newItem) =&gt; {
  	setChildData([...ChildData, newItem]);
  }

  return (
    &lt;div&gt;
        &lt;h1&gt;Test&lt;/h1&gt;
        &lt;div&gt;
          {ChildData.map((data, index) =&gt; &lt;div key={index}&gt;{data}&lt;/div&gt;)}
        &lt;/div&gt;
        &lt;First heading=&quot;First&quot; passChildData={setItem}/&gt;
        &lt;First heading=&quot;Second&quot; passChildData={setItem}/&gt;
    &lt;/div&gt;
  )
}

function First(props) {
  const [Data, setData] = useState(&#39;&#39;);
  const [Items, setItems] = useState([])
  
  useEffect(() =&gt; {
    props.passChildData(Data);
  }, [Items])

  const handlechange = (e)=&gt;{
    setData(e.target.value)
  }
  
  const handleSubmit = (e) =&gt; {
  	e.preventDefault();

    if (Data === &#39;&#39;) {
    	console.log(&#39;enter something&#39;);
    } else {
    	setItems([...Items, Data]);
    }
  }

  return (
    &lt;div&gt;
        &lt;h1&gt;{props.heading}&lt;/h1&gt;
        &lt;form onSubmit={handleSubmit}&gt;
          &lt;input type=&quot;text&quot; onChange={handlechange} value={Data}/&gt;
          &lt;button type=&quot;submit&quot;&gt;Add&lt;/button&gt;
          {Data}
        &lt;/form&gt;
        &lt;div&gt;
          {Items.map((item, index) =&gt; &lt;div key={index}&gt;{item}&lt;/div&gt;)}
        &lt;/div&gt;
    &lt;/div&gt;
  )
}

I have created a fiddle for reference.

答案2

得分: 0

问题在于你在每个组件内部都对整个状态进行了变更。换句话说,你没有使用prevData
我建议在FirstSecond组件的onClick方法中更改状态,就像这样:

setItems((prevData) => {
    const newData = [***...prevData***, ...Items, Data];
    props.passChildData(newData);
    return newData;
})
英文:

The problem is that you are mutating the whole state within every component. In other words, you don't use prevData.
I would change the state in onClick method of First and Second component, like this:

setItems((prevData)=&gt;{
        const newData = [***...prevData***, ...Items,Data];
        props.passChildData(newData)
        return newData
      })

huangapple
  • 本文由 发表于 2023年2月7日 02:07:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75365032.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定