由于我有一个带有表单的组件,我需要将表单连接到组件状态。初始数据来自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>
...
答案 0 :(得分:1)
即使商店和连接的道具发生变化,组件的状态也不会更新
编写文字的方式,除非您使用setState()
(最有可能是componentWillReceiveProps()
方法)明确更新状态,否则状态不会更新。
当您使用mapStateToProps()
与Redux connect()
HOC时,您正在通过道具将Redux状态映射到您的组件,因此在您的情况下this.props.language
将在Redux存储更新时更新。
答案 1 :(得分:1)
首先,您正在为componentWillMount使用箭头功能。经验法则是,请勿将箭头函数用于生命周期挂钩(componentWillMount,shouldComponentUpdate等)。通常在componentWillMount挂钩中设置setState。但是永远不要在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 }))
答案 2 :(得分:1)
要使用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
}
仅在条件setState
内仅运行useEffect
非常重要。
答案 3 :(得分:0)
最初当组件首次安装时,它不会被触发。
您无法在componentwillupdate
内拨打setState
。
为了从redux store初始化组件的初始状态,您应该使用constructor
。
constructor(props) {
super(props);
this.state = {
language: this.props.language || 'en'
}
}
答案 4 :(得分:0)
不确定是否适用,但是最近我遇到了类似的问题,我的情况是由于调用this.setState不能保证 instant 的状态更新;它只是说状态更改将最终生效。
从react-component文档中:
将setState()视为请求而非直接命令 更新组件。为了获得更好的感知性能,React可能会 延迟它,然后在一次通过中更新几个组件。反应 不保证状态更改会立即应用。
setState()并不总是立即更新组件。它可能 批处理或将更新推迟到以后。这使得阅读this.state 在调用setState()之后立即发生潜在的陷阱。相反,使用 componentDidUpdate或setState回调(setState(updater, 回调)),保证在更新后都会触发 已应用。如果您需要根据之前的状态设置状态 状态,请阅读下面的updater参数。
如果您需要对状态或依赖状态的事物进行一些“即时”更改,则setState()上的回调可用于将事物锁定在适当的位置。回调对我有用。
答案 5 :(得分:0)
this.state = {
language: props.language || 'en'
}
无需在状态变量内使用this
。
而且,只有在父组件具有该值的情况下,才能在挂载子组件之前获得实际的道具。
您可以检查父项是否具有值,然后再检查其子级。