[英]Unexpected result with React Hooks setState
I am getting some unexpected results. 我得到了一些意想不到的结果。 Looking at that
看着那个
import React from 'react';
import PropTypes from 'prop-types';
const propTypes = {
fooList: PropTypes.array
};
const defaultProps = {
fooList: [
{ active: false },
{ active: false }
];
};
const FooBar = ({
fooList
}) => {
const [state, setState] = React.useState(fooList);
const onClick = (entry, index) => {
entry.active = !entry.active;
state[index] = entry;
console.log('#1', state) // <- That loggs the new State properly!
setState(state);
}
console.log('#2', state) // <- That does not log at after clicking on the text, only after the initial render
return state.map((entry, index) => {
return <p
onClick={() => onClick(entry, index)}
key={index}>
{`Entry is: ${entry.active ? 'active' : 'not active'}`}
</p>
})
}
FooBar.defaultProps = defaultProps;
FooBar.propTypes = propTypes;
export default FooBar;
I expect on every click the text in the <p />
Tag to change from Entry is: not active
to Entry is: active
. 我希望每次点击
<p />
标记中的文本从Entry is: not active
变为Entry is: active
。
Now, I am not sure if I can simply alter the state like this 现在,我不确定是否可以像这样简单地更改状态
state[index] = entry;
Using a class extending React.Component
, this wouldn't work. 使用扩展
React.Component
的类,这将无法工作。 But maybe with React Hooks? 但是也许有React Hooks? And then, I am not sure if I can use hooks in a
map()
. 然后,我不确定是否可以在
map()
使用钩子。
When you use state[index] = entry;
当您使用
state[index] = entry;
, you are mutating the state but the state reference does not change, and so React will not be able to tell if the state changed, and will not re-render. ,您正在改变状态,但是状态引用不会更改,因此React将无法判断状态是否已更改,并且不会重新呈现。
You can copy the state before mutating it: 您可以在更改状态之前复制状态:
const onClick = (entry, index) => {
entry.active = !entry.active;
const newState = [...state];
newState[index] = entry;
console.log(newState) // <- That loggs the new State properly!
setState(newState);
}
I would also consider maybe changing up your design a little https://stackblitz.com/edit/react-6enuud 我还会考虑也许会稍微改变一下您的设计https://stackblitz.com/edit/react-6enuud
rather than handling each individual click out side, if it is just for display purposes, then it can be easier to encapsulate in a new component: 而不是处理每个单独的点击侧,如果只是用于显示目的,则可以更容易地封装到新组件中:
const FooBarDisplay = (entry) => {
const [active, setActive] = useState(entry.active);
const onClick = () => {
setActive(!active);
}
return (<p onClick={() => onClick()}>
{`Entry is: ${active ? 'active' : 'not active'}`}
</p>
)
}
Here you can make handling state easier, and avoid mutating arrays. 在这里,您可以简化状态处理,并避免对数组进行变异。
Simpler parent: 较简单的父项:
const FooBar = ({
fooList = [
{ active: false },
{ active: false }
]
}) => fooList.map((entry, i) => <FooBarDisplay key={i} entry={entry} />);
I've just moved default props to actual default argument values. 我刚刚将默认道具移到了实际的默认参数值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.