gpt4 book ai didi

javascript - 使用 React useState 钩子(Hook)向循环内的对象添加键值对

转载 作者:行者123 更新时间:2023-12-01 15:42:04 31 4
gpt4 key购买 nike

我正在尝试使用 useState 向对象添加键值对里面 map功能。但是,setContainer({...container, [data.pk]: data.name}); 中的展开操作似乎无效。
下面的代码片段准确地说明了我要解决的问题。事实上,在我的原始代码中 container在另一个 ContextProvider 组件中声明并使用 useContext 引用,但我将其替换为 useState为了简单。
我想这与 setState 的异步特性有关。钩子(Hook),但我不完全理解引擎盖下发生了什么。
请让我知道是什么导致了这个问题以及如何产生我预期的结果。
谢谢你。

const {useState, useEffect} = React;

const myData = [{pk: 1, name:'apple'},
{pk: 2, name:'banana'},
{pk: 3, name:'citrus'},
]

const Example = () => {
const [container, setContainer] = useState({});

useEffect(()=>{
myData.map(data=>{
console.log(`During this iteration, a key-value pair (key ${data.pk} and value '${data.name}') should be added to container`);
setContainer({...container, [data.pk]: data.name});
})
}, [])

return (
<div>
<div>result I expected: {"{'1': 'apple', '2': 'banana','3': 'citrus'}"}</div>
<div>result: {JSON.stringify(container)}</div>
</div>
);
};

// Render it
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

更新
我想使用 useState 的主要原因在循环中是使用状态作为 refs 的容器的组件。但是,我发现这样做效率很低,因为它导致了太多的重新渲染,并且很难确定循环何时结束。经过大量搜索,我最终宣布 useRef({})在 Context Provider 中并将其用作 refs 容器(我猜这似乎符合创建它的实际目的)。 refs 容器可以按如下方式使用:
const refsContainer = useRef({});
import React from 'react';

const Notes = () => {
const setRef = (noteId) => (element) => {
refsContainer.current[noteId] = element
};
return (
<Masonry>
{pubData?.map(publication => {
return <PublicationCard innerRef={setRef(publication.noteId)}/>
})}
</Masonry>
);
};

export default Notes;
const pubCardRef = refsContainer.current[rank.note.noteId];
window.scrollTo({top: pubCardRef?.offsetTop - 80, behavior: 'smooth'})

最佳答案

这是您的组件中逐步发生的事情。

  • containersetContainer使用 useState 初始化 Hook
  • 您在 myData 上映射的效果已注册,并且由于空数组[],它只会在组件的整个生命周期中运行一次你作为第二个参数传递
  • 您在效果中注册的回调运行。如果您控制台记录容器以及键值对
  • ,这就是它的样子

    (key 1 value 'apple'); container {}
    (key 2 value 'banana'); container {}
    (key 3 value 'citrus'); container {}

    Wait what, shouldn't container be updating on each iteration?


    好吧,是的,但不是你期望的那样。 container引用于 useEffect保留其原始 {} myData.map 的每次迭代中的值.然后有效地发生的是
    setContainer({ ...{}, 1: 'apple ' }) // RERENDER
    setContainer({ ...{}, 2: 'banana' }) // RERENDER
    setContainer({ ...{}, 3: 'citrus' }) // RERENDER
    citrus是最后一次显示,因为它是最后一次重新渲染。
    这是一种可以实现所需结果的方法

    const {useState, useEffect} = React;

    const myData = [{pk: 1, name:'apple'},
    {pk: 2, name:'banana'},
    {pk: 3, name:'citrus'},
    ]

    const Example = () => {
    const [container, setContainer] = useState({});

    useEffect(()=>{
    setContainer(myData.reduce((obj, data) => ({ ...obj, [data.pk]: data.name }), {}))
    }, [])

    return (
    <div>
    <div>result I expected: {"{'1': 'apple', '2': 'banana','3': 'citrus'}"}</div>
    <div>result: {JSON.stringify(container)}</div>
    </div>
    );
    };

    // Render it
    ReactDOM.render(
    <Example />,
    document.getElementById("react")
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
    <div id="react"></div>

    关于javascript - 使用 React useState 钩子(Hook)向循环内的对象添加键值对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62597448/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com