Javascript 如何将一个列表元素单独添加到两个列表中?

Javascript 如何将一个列表元素单独添加到两个列表中?,javascript,reactjs,Javascript,Reactjs,我还没有反应过来。所以我有一个父组件,它有两个子组件。这两个子项是应该显示的列表。到目前为止,我通过检查数据的status属性了解了如何在两个列表之间传输数据。我无法理解如何将数据添加到单独的列表中并对其进行编辑,因为父组件呈现了两个列表。有人能解释如何添加和编辑用户将输入的新数据吗?我应该在项目页面上创建新的状态和道具,还是应该在子组件页面上创建它们?我很困惑 import React,{useState,useffect}来自“React” 从“./Completed”导入{Complet

我还没有反应过来。所以我有一个父组件,它有两个子组件。这两个子项是应该显示的列表。到目前为止,我通过检查数据的status属性了解了如何在两个列表之间传输数据。我无法理解如何将数据添加到单独的列表中并对其进行编辑,因为父组件呈现了两个列表。有人能解释如何添加和编辑用户将输入的新数据吗?我应该在项目页面上创建新的状态和道具,还是应该在子组件页面上创建它们?我很困惑

import React,{useState,useffect}来自“React”
从“./Completed”导入{Completed}
从“/Pending”导入{Pending}
导出常量项=()=>{
const[items,setItems]=useState([
{
id:1,
标题:"运动",,
状态:'待定'
},
{
id:2,
标题:“读书”,
状态:'待定'
},
{
id:3,
标题:“烹饪比萨饼”,
状态:'待定'
},
{
id:4,
标题:“付账单”,
状态:'已完成'
},
{
id:5,
标题:“观看大短片”,
状态:'已完成'
},
{
id:6,
标题:“制定营养计划”,
状态:'待定'
}
])
const updateStatus=(id,newStatus)=>{
让allItems=项目;
allItems=allItems.map(项=>{
if(item.id==id){
console.log('in here')
item.status=新闻状态;
}
退货项目
})
集合项目(所有项目)
}
返回(
)
}
从“React”导入React
导出常量挂起=({items,setItems,updateStatus})=>{
返回(
左边
{
items&&items.map(item=>{
如果(项和项状态=='Pending')
return

{item.title}{updateStatus(item.id,'Completed')}>向右移动

}) } ) } 从“React”导入React 导出常量已完成=({items,setItems,updateStatus})=>{ 返回( 正确的 添加 { items&&items.map(item=>{ 如果(项目和项目状态=='Completed') return

{item.title}{updateStatus(item.id,'Pending')}>向左移动

}) } )
}
将状态保存在父对象中并将道具传递给子对象几乎总是更好的。因此,您希望保持您的
项目
状态。您可以创建一个
addItem
函数,并将其作为道具传递给任何子级


我认为不能同时从两个列表中添加项目,因为新项目应该是
“挂起的”
。因此,我建议您将add表单放入一个新组件
AddItem
,它将是
项的第三个子项。一旦
AddItem
从props调用
AddItem
函数,该项目将保存到
items
中的状态,并自动显示在
Pending
列表中

如果所有新项目的状态均为“待定”
,则我们需要添加项目的唯一信息是任务的
标题

此函数用于
项中

const addItem = (title) => {
  // set state using a callback function of current state
  setItems((current) => {
    // the highest number of all current ids, or 0 if empty
    const maxId = current.reduce((max, o) => Math.max(max, o.id), 0);
    // the next id is the max plus 1
    const id = maxId + 1;
    // add new item to the current - concat won't mutate the array
    return current.concat({
      id,
      title,
      status: "Pending"
    });
  });
};
您的
AddItem
组件使用受控的
输入为新项创建文本

export const AddItem = ({ addItem }) => {
  const [title, setTitle] = useState("");

  const handleSubmit = (e) => {
    // prevent form submission from reloading the page
    e.preventDefault();
    // call the addItem function with the current title
    addItem(title);
    // clear the form
    setTitle("");
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        placeholder="enter task"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
      />
      <button type="submit">add</button>
    </form>
  );
};

与手头的问题无关,您还可以对代码进行一些其他改进

您的
updateStatus
函数实际上会对当前的
项进行变异。相反,您应该通过复制除
状态
之外的所有内容来为更改的项目创建新对象

您将收到关于唯一键的警告,因为该键必须位于
.map()
中最外面的组件上。您将一个片段
放在带有
键的
之外,因此删除该片段

在我看来,筛选每个列表中的项目应该由家长完成。您的
Completed
Pending
组件非常相似。您应该将它们组合成一个组件。两者之间的所有不同之处,例如文本和类名,都可以通过传递的道具来控制

import React, { useState } from "react";

export const ItemsList = ({
  items,
  title,
  className,
  buttonText,
  onClickButton
}) => {
  return (
    <div className={className}>
      <h1>{title}</h1>

      {items.map((item) => (
        <p className="item" key={item.id}>
          <span className="item_title">{item.title}</span>
          <button
            className="move_item"
            key={item.id}
            onClick={() => {
              onClickButton(item.id);
            }}
          >
            {buttonText}
          </button>
        </p>
      ))}
    </div>
  );
};

// example of how to compose components
// this keeps the same setup that you had before, but without repeated code
export const Completed = ({ items, updateStatus }) => {
  return (
    <ItemsList
      title="RIGHT"
      buttonText="Move Left"
      className="completed"
      items={items.filter((item) => item.status === "Completed")}
      onClickButton={(id) => updateStatus(id, "Pending")}
    />
  );
};

export const AddItem = ({ addItem }) => {
  const [title, setTitle] = useState("");

  const handleSubmit = (e) => {
    // prevent form submission from reloading the page
    e.preventDefault();
    // call the addItem function with the current title
    addItem(title);
    // clear the form
    setTitle("");
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        placeholder="enter task"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
      />
      <button type="submit">add</button>
    </form>
  );
};

export const Items = () => {
  const [items, setItems] = useState([
    {
      id: 1,
      title: "Workout",
      status: "Pending"
    },
    {
      id: 2,
      title: "Read Books",
      status: "Pending"
    },
    {
      id: 3,
      title: "Cook Pizza",
      status: "Pending"
    },
    {
      id: 4,
      title: "Pay Bills",
      status: "Completed"
    },
    {
      id: 5,
      title: " Watch Big Short",
      status: "Completed"
    },
    {
      id: 6,
      title: " Make nutrition Plan",
      status: "Pending"
    }
  ]);

  const addItem = (title) => {
    // set state using a callback function of current state
    setItems((current) => {
      // the highest number of all current ids, or 0 if empty
      const maxId = current.reduce((max, o) => Math.max(max, o.id), 0);
      // the next id is the max plus 1
      const id = maxId + 1;
      // add new item to the current - concat won't mutate the array
      return current.concat({
        id,
        title,
        status: "Pending"
      });
    });
  };

  const updateStatus = (id, newStatus) => {
    setItems((current) =>
      // arrow function without braces is an implicit return
      current.map((item) =>
        item.id === id
          ? // copy to new item if id matches
            {
              ...item,
              status: newStatus
            }
          : // otherwise return the existing item
            item
      )
    );
  };

  return (
    <div className="items">
      <AddItem addItem={addItem} />
      {/* can set the props on ItemsList here */}
      <ItemsList
        title="LEFT"
        buttonText="Move Right"
        className="pending"
        items={items.filter((item) => item.status === "Pending")}
        // create a function that just takes the `id` and sets the status to "Completed"
        onClickButton={(id) => updateStatus(id, "Completed")}
      />
      {/* or do it in a separate component */}
      <Completed items={items} updateStatus={updateStatus} />
    </div>
  );
};

export default Items;
import React,{useState}来自“React”;
导出常量项目列表=({
项目,
标题
类名,
buttonText,
点击按钮
}) => {
返回(
{title}
{items.map((item)=>(

{item.title} { onclick按钮(item.id); }} > {buttonText}

))} ); }; //如何组合组件的示例 //这将保持与以前相同的设置,但没有重复的代码 导出常量已完成=({items,updateStatus})=>{ 返回( item.status==“已完成”)} onClickButton={(id)=>updateStatus(id,“待定”)} /> ); }; 导出常量AddItem=({AddItem})=>{ const[title,setTitle]=useState(“”); 常量handleSubmit=(e)=>{ //防止表单提交重新加载页面 e、 预防默认值(); //使用当前标题调用addItem函数 增补(标题); //清除表格 片名(“”); }; 返回( setTitle(e.target.value)} /> 添加 ); }; 导出常量项=()=>{ const[items,setItems]=useState([ { id:1, 标题:“训练”,
import React, { useState } from "react";

export const ItemsList = ({
  items,
  title,
  className,
  buttonText,
  onClickButton
}) => {
  return (
    <div className={className}>
      <h1>{title}</h1>

      {items.map((item) => (
        <p className="item" key={item.id}>
          <span className="item_title">{item.title}</span>
          <button
            className="move_item"
            key={item.id}
            onClick={() => {
              onClickButton(item.id);
            }}
          >
            {buttonText}
          </button>
        </p>
      ))}
    </div>
  );
};

// example of how to compose components
// this keeps the same setup that you had before, but without repeated code
export const Completed = ({ items, updateStatus }) => {
  return (
    <ItemsList
      title="RIGHT"
      buttonText="Move Left"
      className="completed"
      items={items.filter((item) => item.status === "Completed")}
      onClickButton={(id) => updateStatus(id, "Pending")}
    />
  );
};

export const AddItem = ({ addItem }) => {
  const [title, setTitle] = useState("");

  const handleSubmit = (e) => {
    // prevent form submission from reloading the page
    e.preventDefault();
    // call the addItem function with the current title
    addItem(title);
    // clear the form
    setTitle("");
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        placeholder="enter task"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
      />
      <button type="submit">add</button>
    </form>
  );
};

export const Items = () => {
  const [items, setItems] = useState([
    {
      id: 1,
      title: "Workout",
      status: "Pending"
    },
    {
      id: 2,
      title: "Read Books",
      status: "Pending"
    },
    {
      id: 3,
      title: "Cook Pizza",
      status: "Pending"
    },
    {
      id: 4,
      title: "Pay Bills",
      status: "Completed"
    },
    {
      id: 5,
      title: " Watch Big Short",
      status: "Completed"
    },
    {
      id: 6,
      title: " Make nutrition Plan",
      status: "Pending"
    }
  ]);

  const addItem = (title) => {
    // set state using a callback function of current state
    setItems((current) => {
      // the highest number of all current ids, or 0 if empty
      const maxId = current.reduce((max, o) => Math.max(max, o.id), 0);
      // the next id is the max plus 1
      const id = maxId + 1;
      // add new item to the current - concat won't mutate the array
      return current.concat({
        id,
        title,
        status: "Pending"
      });
    });
  };

  const updateStatus = (id, newStatus) => {
    setItems((current) =>
      // arrow function without braces is an implicit return
      current.map((item) =>
        item.id === id
          ? // copy to new item if id matches
            {
              ...item,
              status: newStatus
            }
          : // otherwise return the existing item
            item
      )
    );
  };

  return (
    <div className="items">
      <AddItem addItem={addItem} />
      {/* can set the props on ItemsList here */}
      <ItemsList
        title="LEFT"
        buttonText="Move Right"
        className="pending"
        items={items.filter((item) => item.status === "Pending")}
        // create a function that just takes the `id` and sets the status to "Completed"
        onClickButton={(id) => updateStatus(id, "Completed")}
      />
      {/* or do it in a separate component */}
      <Completed items={items} updateStatus={updateStatus} />
    </div>
  );
};

export default Items;