将数组从父组件传递到子组件,然后在父组件中获取返回的筛选数组。

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

Passing array as from Parent to Child and getting back a filtered array in Parent

问题

在Child组件中,有一个删除按钮,点击它应该删除特定的数组元素并将更新后的数组发送回Parent。

它给出了以下输出

输出截图

英文:

I have a Parent component and a Child component.

I am passing an Array from Parent to Child. I want the array to be filtered in the Child and that can be returned back to Parent.

After filtering in Child, it should return a filtered array.

Parent

const Parent = () =>{

const todoData = [
        {id:0,todoname:"Study",todotoday:"Completing CSS today"},
        {id:1,todoname:"Coding",todotoday:"Leetcode 2 Problems"}
    ];
     const [myArray,setmyArray] = useState(todoData);

<div className="todomain">
    {
         myArray.map((obj)=>{
          return ( <div className="todobox" key={obj.id}>
          <div className="checkcont">
           <img src={check} alt="Check" className='chkbtn btn'/>
          </div>
            <h2 className="head" >Todo: {obj.todoname}</h2>
            <h3 className="todocont">{obj.todotoday}</h3>
            <div className="todoboxbtn">
             <Child todoList = {todoData} />
            </div>
            </div> )
        })
      }
      </div>

}

Child

const Child = ({todoData}) =>{
 onst [myArray,setmyArray] = useState(todoData);

    const removeElm = (id) =>{
        const myNewArray = myArray.filter((currElm)=>{
            return currElm.id !== id;
        })

        setmyArray(myNewArray);
    }

  return (
    <div className="todoicon">
    {
        myArray.map((obj)=>{
   return ( <div className='todobtn' key={obj.props.id}>
    <img src={del} alt="Delete" className='deleteBtn btn' onClick={() => removeElm(obj.props.id)}/>
    </div>)
        })
    }
    </div>
  )
}

Expected:

In the Child component, there is a delete button, which on click should delete that particular Array element and send back the updated array to Parent.

It is giving the below output

Screenshot of output

答案1

得分: 2

如果您的目标是在用户从待办事项列表中删除项目时更改父组件的状态,那么您可以简单地将setter传递给子组件。

这样,您可以像这样调用您的组件:

<Child todoList={todoData} changeToDo={setmyArray}/>

并像这样更新您的子组件:

const Child = ({ todoData, changeToDo }) => {
     const removeElm = (id) => {
         changeToDo(myArray.filter((currElm) => {
             return currElm.id !== id;
         }))
     }

   return (
     <div className="todoicon">
     {
         todoData.map((obj) => {
            return ( 
               <div className='todobtn' key={obj.id}>
                   <img src={del} alt="Delete" className='deleteBtn btn' onClick={() => removeElm(obj.id)}/>
               </div>
            )
         })
     }
     </div>
   )
}

请注意,将待办事项保存在子组件的状态中是不必要的。当您去更新父组件的状态时,将执行重新渲染,子组件将会得到其props的更新。

编辑 您期望的行为不会被渲染出来。事实上,您在父组件和子组件中都使用了map迭代。
由于子组件显然只用于显示一个允许删除元素的图像,您不需要将整个TODO列表传递给它。您可以直接在props中将一个onClick函数传递给它,并将它放在图像上。

您的父组件应该像这样:

import { useState } from 'react';
import { Child } from './test2';

const todoData = [
  { id: 0, todoname: 'Study', todotoday: 'Completing CSS today' },
  { id: 1, todoname: 'Coding', todotoday: 'Leetcode 2 Problems' },
];

const Parent = () => {
  const [myArray, setmyArray] = useState(todoData);

  const removeElm = (id) => {
    const myNewArray = myArray.filter((currElm) => {
      return currElm.id !== id;
    });

    setmyArray(myNewArray);
  };

  return (
    <div className="todomain">
      {myArray.map((obj) => {
        return (
          <div className="todobox" key={obj.id}>
            <div className="checkcont">
              <img src={check} alt="Check" className="chkbtn btn" />
            </div>
            <h2 className="head">Todo: {obj.todoname}</h2>
            <h3 className="todocont">{obj.todotoday}</h3>
            <div className="todoboxbtn">
              <Child onDelete={() => removeElm(obj.id)} />
            </div>
          </div>
        );
      })}
    </div>
  );
};

您的子组件应该像这样:

export const Child = ({ onDelete }) => {
  return (
    <div className="todoicon">
      <div className="todobtn">
        <img
          src={del}
          alt="Delete"
          className="deleteBtn btn"
          onClick={onDelete}
        />
      </div>
    </div>
  );
};
英文:

If your goal is to change the state of your parent component when the user deletes an item from your TODO list, then you can simply pass the setter to your child component.

In this way you can call your component like this:

&lt;Child todoList = {todoData} changeToDo={setmyArray}/&gt;

And update your child component like this:

const Child = ({todoData, changeToDo}) =&gt;{
     const removeElm = (id) =&gt;{
         changeTodo(myArray.filter((currElm)=&gt;{
             return currElm.id !== id;
         }))
     }

   return (
     &lt;div className=&quot;todoicon&quot;&gt;
     {
         todoData.map((obj)=&gt;{
            return ( 
               &lt;div className=&#39;todobtn&#39; key={obj.id}&gt;
                   &lt;img src={del} alt=&quot;Delete&quot; className=&#39;deleteBtn btn&#39; onClick={() =&gt; removeElm(obj.id)}/&gt;
               &lt;/div&gt;
            )
         })
     }
     &lt;/div&gt;
   )
}

Note that saving the Todo in a state of your child component is not necessary. When you go to update the state of the parent component, a re-render will be performed and your child will have its props updated

EDIT The behavior you expect is not the one that will be rendered. Indeed, you iterate with map in the parent component and in the child component.
Since the child component apparently only serves to display an image allowing the element to be deleted, you don't need to pass the entire TODOList to it. You could directly pass it a onClick function in props, and put it on your image.

Your parent component should be like this :

import { useState } from &#39;react&#39;;
import { Child } from &#39;./test2&#39;;

const todoData = [
  { id: 0, todoname: &#39;Study&#39;, todotoday: &#39;Completing CSS today&#39; },
  { id: 1, todoname: &#39;Coding&#39;, todotoday: &#39;Leetcode 2 Problems&#39; },
];

const Parent = () =&gt; {
  const [myArray, setmyArray] = useState(todoData);

  const removeElm = (id) =&gt; {
    const myNewArray = myArray.filter((currElm) =&gt; {
      return currElm.id !== id;
    });

    setmyArray(myNewArray);
  };

  return (
    &lt;div className=&quot;todomain&quot;&gt;
      {myArray.map((obj) =&gt; {
        return (
          &lt;div className=&quot;todobox&quot; key={obj.id}&gt;
            &lt;div className=&quot;checkcont&quot;&gt;
              &lt;img src={check} alt=&quot;Check&quot; className=&quot;chkbtn btn&quot; /&gt;
            &lt;/div&gt;
            &lt;h2 className=&quot;head&quot;&gt;Todo: {obj.todoname}&lt;/h2&gt;
            &lt;h3 className=&quot;todocont&quot;&gt;{obj.todotoday}&lt;/h3&gt;
            &lt;div className=&quot;todoboxbtn&quot;&gt;
              &lt;Child onDelete={() =&gt; removeElm(obj.id)} /&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        );
      })}
    &lt;/div&gt;
  );
};

And you child component like this :

export const Child = ({ onDelete }) =&gt; {
  return (
    &lt;div className=&quot;todoicon&quot;&gt;
      &lt;div className=&quot;todobtn&quot;&gt;
        &lt;img
          src={del}
          alt=&quot;Delete&quot;
          className=&quot;deleteBtn btn&quot;
          onClick={onDelete}
        /&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
};

答案2

得分: 2

父组件

// ...
const [filteredArray, setFilteredArray] = useState([]);//添加这个状态
// ...

子组件

// ...
const Child = ({todoList, setFilteredArray}) => {//还有你的 todoData 属性名应该是 todoList
// ...
英文:

You can simply create a new state in the parent and pass its setter function as a prop to the child and set the value using this setter function.

Parent

const Parent = () =&gt;{
const todoData = [
{id:0,todoname:&quot;Study&quot;,todotoday:&quot;Completing CSS today&quot;},
{id:1,todoname:&quot;Coding&quot;,todotoday:&quot;Leetcode 2 Problems&quot;}
];
const [myArray,setmyArray] = useState(todoData);
const [filteredArray, setFilteredArray] = useState([]);//add this state
&lt;div className=&quot;todomain&quot;&gt;
{
myArray.map((obj)=&gt;{
return ( &lt;div className=&quot;todobox&quot; key={obj.id}&gt;
&lt;div className=&quot;checkcont&quot;&gt;
&lt;img src={check} alt=&quot;Check&quot; className=&#39;chkbtn btn&#39;/&gt;
&lt;/div&gt;
&lt;h2 className=&quot;head&quot; &gt;Todo: {obj.todoname}&lt;/h2&gt;
&lt;h3 className=&quot;todocont&quot;&gt;{obj.todotoday}&lt;/h3&gt;
&lt;div className=&quot;todoboxbtn&quot;&gt;
&lt;Child todoList = {todoData} setFilteredArray={setFilteredArray} /&gt;
&lt;/div&gt;
&lt;/div&gt; )
})
}
{/* You can map filteredArray*/}
&lt;/div&gt;
}

Child

const Child = ({todoList, setFilteredArray}) =&gt;{//also your todoData prop name is todoList
const [myArray,setmyArray] = useState(todoData);
const removeElm = (id) =&gt;{
const myNewArray = myArray.filter((currElm)=&gt;{
return currElm.id !== id;
})
setmyArray(myNewArray);
setFilteredArray(myNewArray);
}
return (
&lt;div className=&quot;todoicon&quot;&gt;
{
myArray.map((obj)=&gt;{
return ( &lt;div className=&#39;todobtn&#39; key={obj.props.id}&gt;
&lt;img src={del} alt=&quot;Delete&quot; className=&#39;deleteBtn btn&#39; onClick={() =&gt; removeElm(obj.props.id)}/&gt;
&lt;/div&gt;)
})
}
&lt;/div&gt;
)
}

huangapple
  • 本文由 发表于 2023年6月22日 16:23:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76529905.html
匿名

发表评论

匿名网友

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

确定