[英]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.