【问题标题】:How to add more objects to Array Object state using setState?如何使用 setState 将更多对象添加到 Array Object 状态?
【发布时间】:2021-02-17 11:40:10
【问题描述】:

这是我的初始数据

const data = [
  { id: '1', name: '1' },
  { id: '2', name: '1' },
  { id: '3', name: '2' },
]

我想循环并:

  • name1 将该对象添加到stateOne
  • name2 将该对象添加到stateTwo

两个州的最终目标都需要在其中包含对象数组:

  • stateOne 需要看起来像
[
  { id: '1', name: '1' },
  { id: '2', name: '1' }
]
  • stateTwo 需要看起来像
[
  { id: '3', name: '2' },
]

这是我尝试过的:

const data = [
  { id: '1', name: '1' },
  { id: '2', name: '1' },
  { id: '3', name: '2' },
]

const Testing = () => {
  const [stateOne, setStateOne] = useState([])
  const [stateTwo, setStateTwo] = useState([])

  useEffect(() => {
    data.forEach((e) => {
      if (e.name === '1') {
        console.log('e', e)
        setStateOne((prevSate) => ({ ...prevSate, e }))
      }
      // if (e.name === '2') {
      //   setStateTwo(e)
      // }
    })
  }, [])

  console.log('stateOne', stateOne)
}

【问题讨论】:

  • data 真的是静态的并在 Testing 组件之外定义吗?如果是这样,为什么useEffect
  • 旁注:filter 的目的是创建并返回一个新数组,它通过创建一个新数组并向其中添加条目(如果您的回调返回真值)或不添加条目来实现.如果不使用数组filter 返回,请不要使用filter。只需使用简单的循环遍历数组,或forEach
  • 来自 API 的数据。我只需要将过滤器放置到正确的状态,这样我就可以正确渲染我的组件。我不想使用filter 两次,这是有效的。所以我知道我在 setState 做错了什么
  • 谢谢 T.J.好点,但这可能无法解决我将数据正确传递给 setState 的问题。

标签: javascript reactjs setstate


【解决方案1】:

我更喜欢将 data 作为道具发送到该组件

你可以实现你所需要的


const data = [
  { id: '1', name: '1' },
  { id: '2', name: '1' },
  { id: '3', name: '2' },
]

export default function Testing() {

  const [stateOne, setStateOne] = useState([])
  const [stateTwo, setStateTwo] = useState([])

  useEffect(() => {
    setStateOne(data.filter(e => e.name === "1"))
    setStateTwo(data.filter(e => e.name === "2"))    
    console.log('stateOne', stateOne)
    console.log('stateTwo', stateTwo)
  }, [])
}

【讨论】:

    【解决方案2】:

    setState 用作赋值。就像您通常会分配一个变量一样。这意味着如果你想向一个数组添加一些东西,你需要在赋值中包含那个数组。

    类似这样的:

          if (e.name === '1') {
            console.log('e', e)
            setStateOne([...stateOne, e])
          }
          if (e.name === '2') {
             setStateTwo([...stateTwo, e])
          }
    

    【讨论】:

    • 并且不要使用过滤器...使用 forEach
    • so used forEach 并做到了,但我只是 console.loging 最后一个元素:([{"id":"2","name":"1"}]
    • 在记录更新状态时,您可能无法获得预期的值,因为设置状态是异步的。这篇文章可能对medium.com/@jlangkammer/…有帮助
    【解决方案3】:

    如果您出于某种原因不想使用过滤器两次,您可以为每个过滤器创建临时数组并对其进行操作,然后分别更新每个状态,如下所示:

      const [stateOne, setStateOne] = useState([]);
      const [stateTwo, setStateTwo] = useState([]);
    
      useEffect(() => {
        const tempArr1 = [];
        const tempArr2 = [];
    
        data.forEach((item) => {
          if (item.name === "1") {
            tempArr1.push(item);
          } else if (item.name === "2") {
            tempArr2.push(item);
          }
        });
    
        setStateOne(tempArr1);
        setStateTwo(tempArr2);
      }, []);
    
      console.log(stateOne);
      console.log(stateTwo); 
    

    您所做的问题是每次找到匹配项时都会更新状态,这将导致大量不必要的重新渲染。

    【讨论】:

    • 是的,这个可行,我只是希望我可以避免使用更多变量,例如temp*
    • 那么最良心的回答就是@aytek的恕我直言。
    【解决方案4】:

    您说过data 来自您正在查询的某个API。如果是这样,请在获得数据后过滤数据。您可以通过多种方式做到这一点。

    两次调用filter:

    const Testing = () => {
        const [stateOne, setStateOne] = useState([]);
        const [stateTwo, setStateTwo] = useState([]);
    
        useEffect(() => {
            let cancelled = false;
            getTheData(data => {
                if (cancelled) {
                    return;
                }
                setStateOne(data.filter(({name}) => name === "1"));
                setStateTwo(data.filter(({name}) => name === "2"));
            };
            return () => {
                // So we don't try to set setate on an unmounted component
                cancelled = true;
            };
        }, []);
    
        // ...use `dataOne` and `dataTwo` here...
    };
    

    或者,如果您不想对数据进行两次传递,则使用单个循环:

    const Testing = () => {
        const [stateOne, setStateOne] = useState([]);
        const [stateTwo, setStateTwo] = useState([]);
    
        useEffect(() => {
            let cancelled = false;
            getTheData(data => {
                if (cancelled) {
                    return;
                }
                const stateOne = [];
                const stateTwo = [];
                for (const entry of data) {
                    switch (entry.name) {
                        case "1":
                            stateOne.push(entry);
                            break;
                        case "2": // or default if you want all non-1s in `stateTwo`
                            stateTwo.push(entry);
                            break;
                    }
                }
                setStateOne(stateOne);
                setStateTwo(stateTwo);
            };
            return () => {
                // So we don't try to set setate on an unmounted component
                cancelled = true;
            };
        }, []);
    
        // ...use `dataOne` and `dataTwo` here...
    };
    

    【讨论】:

    • 我喜欢你在 useEffect 中使用 clean up 的方式,需要自己学习并更多地使用它们
    • @Marius - :-) 在异步操作后设置状态很重要,因为在此期间可以卸载组件...
    【解决方案5】:
    
    const data = [
        { id: "1", name: "1" },
        { id: "2", name: "1" },
        { id: "3", name: "2" }
      ];
      
      const App = () => {
        const newdata = useState(data);
        const [stateOne, setStateOne] = useState([]);
        const [stateTwo, setStateTwo] = useState([]);
      
        const Filter = () => {
          let listOne = [];
          let listTwo = [];
          newdata[0].map((it) => {
            if (it.name === "1"){
              listOne.push(it);
            }
            else if(it.name === "2"){
              listTwo.push(it)
            }
          });
          setStateOne(listOne);
          setStateTwo(listTwo);
        };
      
        useEffect(() => {
          Filter();
        }, []);
    
        console.log("stateOne", stateOne)
        console.log("stateTwo", stateTwo)
    
        return (
          // your code
        )
       
      };
    
    

    【讨论】:

      猜你喜欢
      • 2020-09-20
      • 1970-01-01
      • 1970-01-01
      • 2019-05-31
      • 2021-01-27
      • 1970-01-01
      • 2019-10-17
      • 1970-01-01
      • 2019-06-13
      相关资源
      最近更新 更多