[英]React Hook useState value being reset to initial value
The state of a value set using React useState hook gets set to the proper value and then reset to null.使用 React useState hook 设置的值的 state 被设置为正确的值,然后重置为 null。 Critical code below.
下面的关键代码。 The click event that sets the startDate to the current date and time is 3 components down from where startDate is initialized.
将 startDate 设置为当前日期和时间的单击事件是 startDate 初始化位置的 3 个组件。 When setStartDate did not work I created an arrow function, updateStartDate.
当 setStartDate 不起作用时,我创建了一个箭头 function,updateStartDate。 Both had the same problem where the startDate was changed after the click event (witnessed per the console.log in the top component), but was null just before the next click event (per the console.log in the click event).
两者都有相同的问题,即在单击事件之后更改了 startDate(根据顶部组件中的 console.log 见证),但在下一个单击事件之前是 null(根据单击事件中的 console.log)。 This is not an async problem as I see the change made before subsequent click.
这不是异步问题,因为我看到在后续单击之前所做的更改。
If this is something that just does not work please explain.如果这不起作用,请解释。 I could probably fix with useReducer but prefer to keep the useState if there is something I can do to correct this... If not correctable then I would like to at least understand why it does not work so that I can avoid this problem in the future.
我可能可以使用 useReducer 进行修复,但如果我可以采取一些措施来纠正这个问题,我更愿意保留 useState ......如果无法纠正,那么我想至少了解它为什么不起作用,这样我就可以在未来。
export const DisplayTicTacToeContainer = (props) => {
const [startDate, setStartDate]= useState();
const updateStartDate = (newDate) => {
setStartDate(newDate);
}
useEffect (() => {
setStartDate(null);
}, []);
useEffect(() => {
console.log( "displayTicTacToeContainer useEffect for change of startDate = ", startDate)
}, [startDate]);
return (
<DisplayTicTacToeMatch arrayOfMatchingItems ={arrayOfMatchingItems}
startDate={startDate}
setStartDate={setStartDate}
updateStartDate={updateStartDate}
/>);
}
//-----------------------------------------------
export const DisplayTicTacToeMatch = (props) => {
const { startDate,
setStartDate,
updateStartDate,
} = props;
useEffect(() => {
// Performs some prep and working fine.
}, []);
return (
<TicTacToe
startDate={startDate}
setStartDate={setStartDate}
updateStartDate={updateStartDate}
/>
);
}
//-----------------------------------------------
const TicTacToeContainer = (props) => {
const { startDate,
setStartDate,
updateStartDate,
} = props;
const [board, setBoard] = useState(<Board
updateStartDate={updateStartDate}
startDate={startDate}
setStartDate={setStartDate}/>);
return (
<Board/>
)
}
export default TicTacToeContainer;
I renamed the component to BoardComponent and the state variable to boardLayout.我将组件重命名为 BoardComponent,并将 state 变量重命名为 boardLayout。 I included the full return portion of the BoardComponent below.
我在下面包含了 BoardComponent 的全部返回部分。
As I am still experiencing the problem I would agree with you that, "DisplayTicTacToeContainer is being mounted twice".由于我仍然遇到这个问题,我同意你的观点,“DisplayTicTacToeContainer 正在安装两次”。 Any thoughts on how I can avoid this from happening?
关于如何避免这种情况发生的任何想法?
Other than this inability to setStartDate, everything is working fine.除了无法设置开始日期外,一切正常。
//-----------------------------------------------
const Board = (props) => {
const { updateStartDate,
startDate,
setStartDate,
} = props;
return (
<>
<Grid container maxwidth="lg" alignItems="center" spacing={1}>
<Grid item xs={9}>
<Grid container alignItems="center">
<Grid item xs={9}>
<Typography variant = "body1">
First select a square. Once the "Inquiry" word or phrase appears below, find
the correct response in the column on the right and select that buttton. A correct
response will fill the square previously selected with an "O" or "X".
</Typography>
<div style={{ width: '100%' }}>
<Box
display="flex"
flexWrap="wrap"
p={1}
m={1}
bgcolor="background.paper"
css={{ maxWidth: 900 }}
>
<Box p={1} bgcolor="grey.300">
Inquiry : {inquiry}
</Box>
</Box>
<Box
display="flex"
flexWrap="wrap"
p={1}
m={1}
bgcolor="background.paper"
css={{ maxWidth: 900 }}
>
<Box p={1} bgcolor="grey.300">
Next move by : {currentPlayer}
</Box>
<Box p={1} bgcolor="grey.300">
{showStatus}
</Box>
</Box>
</div>
</Grid>
</Grid>
<MyAux>
{boardLayout.map((row, rowId) => {
const columns = row.map((column, columnId) => (
<Grid key={columnId} item>
<ButtonBase >
<Paper
onClick={(e) => {
clickSquareHandler(e);
}}
elevation={4}
data-coord={rowId + ':' + columnId}
id={"Square" + rowId.toString() + columnId.toString()}
className={classes.Paper}>
<Icon
className={classes.Icon}
style={{fontSize: 78}}>
</Icon>
</Paper>
</ButtonBase>
</Grid>
));
return (
<Grid
key={rowId}
className={classes.Grid}
container
spacing={2}>
{columns}
</Grid>)
})}
</MyAux>
</Grid>
<Grid item xs={3} >
<Paper className={classes.paper}>
<Typography variant = "body1">
Response Options
</Typography>
<ButtonGroup
orientation="vertical"
color="secondary"
aria-label="vertical outlined secondary button group"
>
{responseChoices.map((choice) => (
<Controls.Button
key ={choice.value}
text={choice.value}
variant="contained"
color = "secondary"
onClick={() => {
chooseChecker(choice);
}}
className={
response && response.value === choice.value ? "selected" : ""
}
disabled={!!selected[choice.value]}
fullWidth = "true"
size = "small"
/>
))}
</ButtonGroup>
</Paper>
</Grid>
</Grid>
</>
)
}
BoardContainer.propTypes = {
won: PropTypes.func,
size: PropTypes.number
};
export default BoardContainer;
At least, code below doesn't make much sense.至少,下面的代码没有多大意义。 Please don't set state value as a component.
请不要将 state 值设置为组件。 Also, try to name state variable different from components, since it will confuse you at some ppint.
此外,尝试将 state 变量命名为与组件不同的变量,因为它会使您在某些方面感到困惑。
const [board, setBoard] = useState(<Board
updateStartDate={updateStartDate}
startDate={startDate}
setStartDate={setStartDate}/>);
return (
<Board/>
)
Another possibility is that the DisplayTicTacToeContainer
is being mounted twice, but I can't confirm it with the code provided.另一种可能性是
DisplayTicTacToeContainer
被安装了两次,但我无法使用提供的代码进行确认。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.