[英]How to update component state on redux state change?
由于我有一个带有表单的组件,我需要将表单连接到组件状态。 初始数据来自 Redux,因此尝试通过使用 props 设置状态来初始化和更新组件:
componentWillMount = () => {
this.setState({
language: this.props.language || 'en'
})
}
language
是一个连接道具,我检查了它是否在商店中更新。
const mapStateToProps = state => ({
language: state.language
})
我也尝试使用componentWillReceiveProps
和componentWillUpdate
但它不起作用。 我得到了初始状态,即使商店和连接的道具发生了变化,组件的状态也不会更新。
{this.props.language} // updates
{this.state.language} // doesn't change
从 Redux 数据管理表单的正确方法是什么?
render
部分:
render () {
const {classes, theme, web} = this.props
const language = (
<CardContent>
<Typography type="headline">
Language
</Typography>
<Divider/>
<form className={classes.container} autoComplete="off">
<FormControl fullWidth margin="normal">
<InputLabel htmlFor="language">Select Block</InputLabel>
<Select
value={this.state.language} // <==================== language
onChange={this.handleLanguaheChange}
input={<Input id="language"/>}
>
<MenuItem value={'en'}>English</MenuItem>
<MenuItem value={'he'}>עברית</MenuItem>
</Select>
</FormControl>
</form>
</CardContent>
)
...
return (
<Grid
container
spacing={theme.spacing.unit * 3}
justify={'space-between'}
className={classes.gridWrap}
>
<Grid item xs={6}>
<Card className={classes.card}>
{language}
</Card>
...
首先,您正在为 componentWillMount 使用箭头函数。 经验法则是,不要将箭头函数用于生命周期钩子(componentWillMount、shouldComponentUpdate 等)。 通常在 componentWillMount 钩子中设置状态。 但永远不要在 componentDidMount 中设置状态。 请尝试将其重写为,
constructor(props) {
super(props)
this.state = {
language: 'en',
}
}
componentWillMount() {
const { language } = this.props
if (language) this.setState(prevState => ({ language: prevState.language = language }))
}
在某些特殊情况下,例如我在一个 .js 文件中编写了两个类(就像我说的,有些例外)并且我无法按预期从 componentWillMount 修改它(后来指出,道具是由孩子修改的类)。 在这种情况下,您可以在渲染中覆盖它
render() {
const { language } = this.props
if (language) this.setState(prevState => ({ language: prevState.language = language }))
要使用 React Hooks 完成此操作:
useRef()
跟踪先前的值发布的示例对我来说并没有真正意义,所以这是我面临的问题:
我有一个带有组件状态的表单,当 redux 状态改变时我需要清除它。
为了实现这一点,我的组件如下所示:
import { useSelector } from 'react-redux';
import React, { useState, useEffect, useRef } from 'react';
const CreateCase = () => {
//redux state
const accounts = useSelector(state => state.accounts);
//component state
const [productId, setProductId] = useState(undefined);
const prevAccountRef = useRef<string>();
useEffect(() => {
//compare current with previous account and clear productId if changed
if (account.id != prevAccountRef.current) {
setProductId(undefined);
}
//set previous account for next render
prevAccountRef.current = account.id;
});
//... render
}
仅在useEffect
有条件地运行setState
非常重要。
即使商店和连接的道具发生变化,组件的状态也不会更新
按照您编写的方式,状态不会更新,除非您使用setState()
(最有可能在componentWillReceiveProps()
方法中)显式更新它。
当您将mapStateToProps()
与 Redux connect()
HOC 一起使用时,您正在通过其props将您的 Redux 状态映射到您的组件,因此在您的情况下, this.props.language
将在 Redux 存储更新时更新。
componentWillReceiveProps
只会在你的组件重新渲染时被调用。
最初当组件第一次安装时,它不会触发。
您不能在componentwillupdate
内调用setState
。
为了从 redux store 初始化组件的初始状态,你应该使用constructor
。
constructor(props) {
super(props);
this.state = {
language: this.props.language || 'en'
}
}
不确定这是否适用,但我最近遇到了类似的问题,我的情况是由于调用 this.setState 并不能保证立即更新状态; 它只是说最终会影响状态更改。
从反应组件文档:
将 setState() 视为更新组件的请求而不是立即命令。 为了获得更好的感知性能,React 可能会延迟它,然后一次更新多个组件。 React 不保证状态更改会立即应用。
setState() 并不总是立即更新组件。 它可能会批量更新或推迟更新。 这使得在调用 setState() 之后立即读取 this.state 成为一个潜在的陷阱。 相反,请使用 componentDidUpdate 或 setState 回调 (setState(updater, callback)),这两者都保证在应用更新后触发。 如果您需要根据之前的状态设置状态,请阅读下面的更新程序参数。
如果您需要对状态或依赖状态的事物进行一些“即时”更改,则可以使用 setState() 上的回调将事物锁定到位。 回调对我有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.