フォームを持つコンポーネントがあるため、コンポーネントの状態にフォームを接続する必要があります。初期データは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フックで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ファイルに2つのクラスを書いた(私が言ったように、いくつかの例外)と期待どおりにcomponentWillMountからそれを変更することができませんでした(後で、小道具は子によって変更されますクラス)。そのような場合は、レンダリングでオーバーライドできます
render() {
const { language } = this.props
if (language) this.setState(prevState => ({ language: prevState.language = language }))
ストアと接続されている小道具が変わっても、コンポーネントの状態は更新されません
書き方では、setState()
(ほとんどの場合componentWillReceiveProps()
メソッドで)を使用して明示的に更新しない限り、状態は更新されません。
Redux mapStateToProps()
HOCでconnect()
を使用すると、propsを介してReduxの状態がコンポーネントにマッピングされるため、_this.props.language
は、Reduxが更新を保存すると更新されます。
componentWillReceiveProps
は、コンポーネントが再レンダリングされたときにのみ呼び出されます。
最初にコンポーネントが初めてマウントされるとき、トリガーされません。
setState
内でcomponentwillupdate
を呼び出すことはできません。
Reduxストアからコンポーネントの初期状態を初期化するには、constructor
を使用する必要があります。
constructor(props) {
super(props);
this.state = {
language: this.props.language || 'en'
}
}
これが当てはまるかどうかはわかりませんが、最近、同様の問題に遭遇しました。私の場合は、this.setStateを呼び出してもinstant状態の更新が保証されないためです。状態の変更が最終的に行われることを示しているだけです。
反応コンポーネントのドキュメントから:
SetState()は、コンポーネントを更新するための即時コマンドではなく、リクエストと考えてください。パフォーマンスを向上させるために、Reactはそれを遅らせ、1回のパスで複数のコンポーネントを更新できます。Reactは、状態の変更がすぐに適用されることを保証しません。
setState()は、常にすぐにコンポーネントを更新するとは限りません。更新がバッチ処理されるか、後まで延期される場合があります。これにより、setState()を呼び出した直後にthis.stateを読み取ることが潜在的な落とし穴になります。代わりに、componentDidUpdateまたはsetStateコールバック(setState(updater、callback))を使用します。どちらも、更新が適用された後に起動することが保証されています。前の状態に基づいて状態を設定する必要がある場合は、以下のupdater引数についてお読みください。
状態または状態に依存するものにいくつかの「インスタント」変更を行う必要がある場合は、setState()にコールバックがあり、それを使用して適切な場所にロックできます。コールバックは私のために働いたものです。