Javascript 使用React-useState钩子向循环内的对象添加键值对
我正在尝试使用Javascript 使用React-useState钩子向循环内的对象添加键值对,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我正在尝试使用useStateinsidemap函数向对象添加键值对。但是,setContainer({…container[data.pk]:data.name})中的扩展操作似乎无效 下面的代码片段正好说明了我试图解决的问题。事实上,在我的原始代码中,容器在另一个ContextProvider组件中声明,并使用useContext引用,但为了简单起见,我将其替换为useState 我想这与setStatehook的异步特性有关,但我不完全理解引擎盖下到底发生了什么 请让我知道是什么导致了这个
useState
insidemap
函数向对象添加键值对。但是,setContainer({…container[data.pk]:data.name})中的扩展操作代码>似乎无效
下面的代码片段正好说明了我试图解决的问题。事实上,在我的原始代码中,容器
在另一个ContextProvider组件中声明,并使用useContext
引用,但为了简单起见,我将其替换为useState
我想这与setState
hook的异步特性有关,但我不完全理解引擎盖下到底发生了什么
请让我知道是什么导致了这个问题,以及如何产生我预期的结果。
多谢各位
const{useState,useffect}=React;
const myData=[{pk:1,名称:'apple'},
{pk:2,名称:'banana'},
{pk:3,名称:'citrus'},
]
常量示例=()=>{
const[container,setContainer]=useState({});
useffect(()=>{
myData.map(数据=>{
log(`在此迭代过程中,应将键值对(key${data.pk}和value'${data.name}')添加到容器`);
setContainer({…container[data.pk]:data.name});
})
}, [])
返回(
我期望的结果:{{'1':'apple','2':'banana','3':'citruss'}}
结果:{JSON.stringify(容器)}
);
};
//渲染它
ReactDOM.render(
,
document.getElementById(“react”)
);代码>
你说得对,这是因为setState
hook的异步特性,它基本上是成批运行的
发件人:
setState()不会立即改变this.state,但会创建挂起的状态转换。调用此方法后访问this.state可能会返回现有值。无法保证对setState调用的同步操作,并且可能会对调用进行批处理以提高性能
可以先创建对象,然后在循环完成后进行设置。你也不应该在这里使用。因为您没有创建新数组
useffect(()=>{
常量dataObj={};
myData.forEach(数据=>{
dataObj[data.pk]=data.name;
});
setContainer(dataObj);
}, []);代码>以下是您的组件中逐步发生的情况
container
和setContainer
使用useState
钩子进行初始化
映射到myData
的效果已被注册,而且由于作为第二个参数传递的是空数组[]
,因此它在组件的整个生命周期中将只运行一次
您在效果中注册的回调将运行。如果您对容器以及键值对进行控制台.log'd,则会出现这种情况
(键1值“苹果”);容器{}
(键2值“香蕉”);容器{}
(关键3值“柑橘”);容器{}
等等,容器不应该在每次迭代时更新吗
嗯,是的,但不是以你期望的方式。useffect
中引用的容器
在myData.map
的每次迭代中保留其原始的{}
值。那么实际上发生的是
setContainer({…{},1:'apple'})//重新加载
setContainer({…{},2:'banana'})//重新加载
setContainer({…{},3:'citrus'})//重新加载
citrus
是最后一次重播后的最终显示
这里有一个方法可以让你达到你想要的结果
const{useState,useffect}=React;
const myData=[{pk:1,名称:'apple'},
{pk:2,名称:'banana'},
{pk:3,名称:'citrus'},
]
常量示例=()=>{
const[container,setContainer]=useState({});
useffect(()=>{
setContainer(myData.reduce((obj,data)=>({…obj[data.pk]:data.name}),{}))
}, [])
返回(
我期望的结果:{{'1':'apple','2':'banana','3':'citruss'}}
结果:{JSON.stringify(容器)}
);
};
//渲染它
ReactDOM.render(
,
document.getElementById(“react”)
);代码>
将setstate中的逻辑从中取出,并使用新对象仅调用setstate一次。