J'ai des problèmes avec un formulaire React et je gère correctement l'état. J'ai un champ de saisie de temps dans un formulaire (dans un modal). La valeur initiale est définie comme une variable d'état dans getInitialState
et est transmise à partir d'un composant parent. Cela fonctionne bien en soi.
Le problème survient lorsque je souhaite mettre à jour la valeur start_time par défaut via le composant parent. La mise à jour elle-même se produit dans le composant parent via setState start_time: new_time
. Cependant, dans ma forme, la valeur par défaut start_time ne change jamais, car elle n'est définie qu'une seule fois getInitialState
.
J'ai essayé de componentWillUpdate
forcer un changement d'état à travers setState start_time: next_props.start_time
, ce qui a effectivement fonctionné, mais m'a donné des Uncaught RangeError: Maximum call stack size exceeded
erreurs.
Ma question est donc la suivante: quelle est la bonne façon de mettre à jour l'état dans ce cas? Est-ce que je pense mal à cela d'une manière ou d'une autre?
Code actuel:
@ModalBody = React.createClass
getInitialState: ->
start_time: @props.start_time.format("HH:mm")
#works but takes long and causes:
#"Uncaught RangeError: Maximum call stack size exceeded"
componentWillUpdate: (next_props, next_state) ->
@setState(start_time: next_props.start_time.format("HH:mm"))
fieldChanged: (fieldName, event) ->
stateUpdate = {}
stateUpdate[fieldName] = event.target.value
@setState(stateUpdate)
render: ->
React.DOM.div
className: "modal-body"
React.DOM.form null,
React.createElement FormLabelInputField,
type: "time"
id: "start_time"
label_name: "Start Time"
value: @state.start_time
onChange: @fieldChanged.bind(null, "start_time”)
@FormLabelInputField = React.createClass
render: ->
React.DOM.div
className: "form-group"
React.DOM.label
htmlFor: @props.id
@props.label_name + ": "
React.DOM.input
className: "form-control"
type: @props.type
id: @props.id
value: @props.value
onChange: @props.onChange
[..]going to be deprecated in the future
Apparemment, les choses changent ... getDerivedStateFromProps () est maintenant la fonction préférée.
(ci-dessus code par danburzo @ github)
la source
null
si rien ne devrait changer, donc juste après votre si, vous devriez y aller avecreturn null
getDerivedStateFromProps
ou l' autre ou la mémorisation reactjs.org/blog/2018/06/07/…componentWillReceiveProps
est obsolète car son utilisation "conduit souvent à des bogues et des incohérences".Si quelque chose change de l'extérieur, envisagez de réinitialiser entièrement le composant enfant avec
key
.Fournir un
key
accessoire au composant enfant garantit que chaque fois que la valeur deskey
changements de l'extérieur, ce composant est re-rendu. Par exemple,Sur ses performances:
la source
JSON.stringify(myObject)
pour dériver une clé unique de votre objet.ComponentDidUpdate est également disponible.
Signatur de fonction:
Profitez-en pour opérer sur le DOM lorsque le composant a été mis à jour. N'est pas appelé lors de l'initiale
render
.Voir que vous n'avez probablement pas besoin d'un article sur l' état dérivé , qui décrit Anti-Pattern pour les deux
componentDidUpdate
etgetDerivedStateFromProps
. Je l'ai trouvé très utile.la source
componentDidUpdate
parce que c'est simple et c'est plus adapté à la plupart des cas.La nouvelle façon de procéder avec hooks consiste à utiliser useEffect au lieu de componentWillReceiveProps à l'ancienne:
devient le suivant dans un composant piloté par des crochets fonctionnels:
nous définissons l'état en utilisant setState, en utilisant useEffect, nous vérifions les modifications apportées au prop spécifié, et prenons l'action pour mettre à jour l'état lors du changement de prop.
la source
Vous n'avez probablement pas besoin d'un état dérivé
1. Définissez une clé du parent
2. Utilisez
getDerivedStateFromProps
/componentWillReceiveProps
En utilisant,
getDerivedStateFromProps
vous pouvez réinitialiser n'importe quelle partie de l'état mais cela semble un peu bogué pour le moment (v16.7) !, voir le lien ci-dessus pour l'utilisationla source
De la documentation de réaction: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
Depuis React 16, componentWillReceiveProps est obsolète. À partir de la documentation de react, l'approche recommandée dans ce cas est l'utilisation
ParentComponent
laModalBody
volonté de posséder l'start_time
état. Ce n'est pas mon approche préférée dans ce cas car je pense que le modal devrait posséder cet état.start_time
état de votreModalBody
et l'utilisergetInitialState
comme vous l'avez déjà fait. Pour réinitialiser l'start_time
état, il vous suffit de changer la clé duParentComponent
la source
C'est assez clairement d'après leurs documents:
Utilisez: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization
la source
Utiliser Memoize
La dérivation d'état de l'op est une manipulation directe des accessoires, sans véritable dérivation nécessaire. En d'autres termes, si vous avez un accessoire qui peut être utilisé ou transformé directement, il n'est pas nécessaire de stocker l'accessoire sur l'état .
Etant donné que la valeur d'état de
start_time
est simplement le propstart_time.format("HH:mm")
, les informations contenues dans le prop sont déjà en soi suffisantes pour mettre à jour le composant.Cependant, si vous ne vouliez appeler le format que sur un changement d'accessoire, la bonne façon de le faire selon la dernière documentation serait via Memoize: https://reactjs.org/blog/2018/06/07/you-probably-dont- état-dérivé du besoin.html # what-about-memoization
la source
Je pense que l'utilisation de ref est sans danger pour moi, je n'ai pas besoin de vous soucier de la méthode ci-dessus.
la source