web-dev-qa-db-fra.com

Comment mettre à jour l'état du composant lors d'un changement d'état redux?

Étant donné que j'ai un composant avec des formulaires, j'ai besoin que les formulaires soient connectés à l'état du composant. Les données initiales proviennent de Redux, essayez donc d'initialiser et de mettre à jour le composant en définissant l'état avec les accessoires:

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

language est un accessoire connecté et j'ai vérifié qu'il est mis à jour dans le magasin.

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

J'ai également essayé d'utiliser componentWillReceiveProps et componentWillUpdate mais cela ne fonctionne pas. J'obtiens l'état initial, et même si le magasin et les accessoires connectés changent, l'état du composant n'est pas mis à jour.

{this.props.language} // updates
{this.state.language} // doesn't change

Quelle est la bonne façon de gérer les formulaires à partir des données Redux?


La partie 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

Tout d'abord, vous utilisez une fonction de flèche pour componentWillMount. La règle générale est de ne pas utiliser les fonctions fléchées pour les crochets du cycle de vie (componentWillMount, shouldComponentUpdate, ... etc). Il est habituel de définirState dans le hook componentWillMount. Mais ne définissez jamais l'état dans componentDidMount. veuillez essayer de le réécrire comme,

constructor(props) {
 super(props)
 this.state = {
  language: 'en',
 }
}
componentWillMount() {
 const { language } = this.props
 if (language) this.setState(prevState => ({ language: prevState.language = language }))
}

dans certains cas exceptionnels, comme j'ai écrit deux classes dans un seul fichier .js (comme je l'ai dit, quelques exceptions) et je ne pouvais pas le modifier à partir de componentWillMount comme prévu (noté plus tard, les accessoires sont modifiés par l'enfant classe). dans de tels cas, vous pouvez le remplacer dans le rendu

render() {
 const { language } = this.props
 if (language) this.setState(prevState => ({ language: prevState.language = language }))
2
sarathantony

même si le magasin et les accessoires connectés changent, l'état du composant ne se met pas à jour

De la façon dont vous l'avez écrit, l'état ne sera pas mis à jour à moins que vous ne le mettiez explicitement à jour à l'aide de setState() (très probablement dans la méthode componentWillReceiveProps()).

Lorsque vous utilisez mapStateToProps() avec le Redux connect() HOC, vous mappez votre état Redux à votre composant via son props, donc dans votre cas this.props.language sera mis à jour lorsque le Redux aura stocké les mises à jour.

1
T Porter

componentWillReceiveProps ne sera appelé que lorsque votre composant sera restitué.

Initialement lors du premier montage du composant, il ne se déclenchera pas.

Vous ne pouvez pas appeler setState à l'intérieur componentwillupdate .

Afin d'initialiser l'état initial du composant à partir du magasin redux, vous devez utiliser constructor.

    constructor(props) {

    super(props);

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

Je ne sais pas si cela s'applique, mais j'ai rencontré récemment un problème similaire et mon cas est dû au fait que l'appel à this.setState ne garantit pas une mise à jour instantanée à l'état; il indique seulement que le changement d'état sera finalement réalisé.

De la documentation de React-Component:

Considérez setState () comme une demande plutôt que comme une commande immédiate pour mettre à jour le composant. Pour de meilleures performances perçues, React peut le retarder, puis mettre à jour plusieurs composants en une seule passe. React ne garantit pas que les changements d'état sont appliqués immédiatement).

setState () ne met pas toujours à jour immédiatement le composant. Il peut par lots ou différer la mise à jour à plus tard. Cela rend la lecture de this.state juste après avoir appelé setState () un piège potentiel. À la place, utilisez componentDidUpdate ou un rappel setState (setState (updater, callback)), dont l'un est garanti de se déclencher après l'application de la mise à jour. Si vous devez définir l'état en fonction de l'état précédent, lisez l'argument de mise à jour ci-dessous.

Si vous devez apporter des modifications "instantanées" à l'état ou des choses qui dépendent de l'état, alors il y a ce rappel sur setState () que vous pouvez utiliser pour verrouiller les choses en place. Le rappel est ce qui a fonctionné pour moi.

0
JESii