我得到了一些意想不到的结果。 看着那个
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;
我希望每次点击<p />
标记中的文本都会从Entry is: not active
变为Entry is: active
。
现在,我不确定是否可以像这样简单地更改状态
state[index] = entry;
使用扩展React.Component
的类,此操作将无效。但是也许有React Hooks?然后,我不确定是否可以在map()
中使用钩子。
答案 0 :(得分:4)
使用state[index] = entry;
时,您是在改变状态,但是状态引用没有改变,因此React将无法判断状态是否改变,并且也不会重新呈现。
您可以在更改状态之前复制状态:
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);
}
答案 1 :(得分:0)
我还会考虑也许对您的设计进行一点https://stackblitz.com/edit/react-6enuud
如果仅出于显示目的,而不是处理每个单独的点击侧,则可以更容易地将其封装在新组件中:
const FooBarDisplay = (entry) => {
const [active, setActive] = useState(entry.active);
const onClick = () => {
setActive(!active);
}
return (<p onClick={() => onClick()}>
{`Entry is: ${active ? 'active' : 'not active'}`}
</p>
)
}
在这里,您可以使处理状态更加容易,并避免对数组进行变异。
简单的父母:
const FooBar = ({
fooList = [
{ active: false },
{ active: false }
]
}) => fooList.map((entry, i) => <FooBarDisplay key={i} entry={entry} />);
我刚刚将默认道具转移到实际的默认参数值。