web-dev-qa-db-ja.com

redux状態の変更時にコンポーネントの状態を更新する方法は?

フォームを持つコンポーネントがあるため、コンポーネントの状態にフォームを接続する必要があります。初期データはReduxから取得されるため、propsで状態を設定してコンポーネントを初期化および更新してみてください。

componentWillMount = () => {
  this.setState({
    language: this.props.language || 'en'
  })
}

languageは接続されたプロップであり、ストアで更新されることを確認しました。

const mapStateToProps = state => ({
  language: state.language
})

componentWillReceivePropscomponentWillUpdateも使用しようとしましたが、機能しません。私は初期状態を取得し、ストアと接続されている小道具が変わっても、コンポーネントの状態は更新されません。

{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>
...
14
ilyo

まず、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 }))
2
sarathantony

ストアと接続されている小道具が変わっても、コンポーネントの状態は更新されません

書き方では、setState()(ほとんどの場合componentWillReceiveProps()メソッドで)を使用して明示的に更新しない限り、状態は更新されません。

Redux mapStateToProps() HOCでconnect()を使用すると、propsを介してReduxの状態がコンポーネントにマッピングされるため、_this.props.languageは、Reduxが更新を保存すると更新されます。

1
T Porter

componentWillReceiveProps は、コンポーネントが再レンダリングされたときにのみ呼び出されます。

最初にコンポーネントが初めてマウントされるとき、トリガーされません。

setState 内でcomponentwillupdateを呼び出すことはできません。

Reduxストアからコンポーネントの初期状態を初期化するには、constructorを使用する必要があります。

    constructor(props) {

    super(props);

    this.state = {
        language: this.props.language || 'en'
     }
   }
0
RIYAJ KHAN

これが当てはまるかどうかはわかりませんが、最近、同様の問題に遭遇しました。私の場合は、this.setStateを呼び出してもinstant状態の更新が保証されないためです。状態の変更が最終的に行われることを示しているだけです。

反応コンポーネントのドキュメントから:

SetState()は、コンポーネントを更新するための即時コマンドではなく、リクエストと考えてください。パフォーマンスを向上させるために、Reactはそれを遅らせ、1回のパスで複数のコンポーネントを更新できます。Reactは、状態の変更がすぐに適用されることを保証しません。

setState()は、常にすぐにコンポーネントを更新するとは限りません。更新がバッチ処理されるか、後まで延期される場合があります。これにより、setState()を呼び出した直後にthis.stateを読み取ることが潜在的な落とし穴になります。代わりに、componentDidUpdateまたはsetStateコールバック(setState(updater、callback))を使用します。どちらも、更新が適用された後に起動することが保証されています。前の状態に基づいて状態を設定する必要がある場合は、以下のupdater引数についてお読みください。

状態または状態に依存するものにいくつかの「インスタント」変更を行う必要がある場合は、setState()にコールバックがあり、それを使用して適切な場所にロックできます。コールバックは私のために働いたものです。

0
JESii