2017-09-14 1 views
0

Je la forme suivante:Pourquoi Réagir Remise à zéro/re-rendu sous forme

import React from 'react'; 
import {connect} from 'react-redux'; 
import {bindActionCreators} from 'redux'; 
import {apiUpdateUser} from '../../redux/actions/user'; 

class EditUser extends React.Component { 

    constructor(props) { 
    super(props); 
    this.onSubmit = this.onSubmit.bind(this); 
    this.onChange = this.onChange.bind(this); 
    }; 

    onSubmit(e) { 
    e.preventDefault(); 
    this.props.apiUpdateUser('/users_api/users/edit-user', this.state, true); 
    }; 

    onChange(e) { 
    const target = e.target; 
    const value = target.type === 'checkbox' ? target.checked : target.value; 
    const name = target.name; 
    this.setState({[name]: value}); 
    }; 

    render() { 
    const btnText = 'Submit' 
    return (
     <div> 
     <h2>Edit My Details</h2> 
     <form onSubmit={this.onSubmit}> 
      <div> 
      <label htmlFor="inputEmail" className="sr-only">Email</label> 
      <input 
       type="email" 
       name="username" 
       id="inputEmail" 
       placeholder="Email address" 
       onChange={this.onChange} 
       required 
       autoFocus 
      /> 
      </div> 

      <div> 
      <label htmlFor="inputName" className="sr-only">Name</label> 
      <input 
       type="text" 
       name="name" 
       id="inputName" 
       placeholder="Users First Name" 
       onChange={this.onChange} 
       autoFocus 
      /> 
      </div> 

      <div> 
      <label htmlFor="pw-new" className="sr-only">New Password</label> 
      <input 
      type="password" 
      name="passwordNew" 
      id="pw-new" 
      placeholder="Password" 
      onChange={this.onChange} 
      /> 
      </div> 

      <div> 
      <label htmlFor="pw-confirm" className="sr-only">Password Confirmation</label> 
      <input 
      type="password" 
      name="passwordConfirm" 
      id="pw-confirm" 
      placeholder="Password Confirmation" 
      onChange={this.onChange} 
      /> 
      </div> 

      <div> 
      <br /> 
      <label htmlFor="password" className="sr-only">Current Password</label> 
      <input 
      type="password" 
      name="password" 
      id="password" 
      placeholder="Current Password" 
      onChange={this.onChange} 
      required 
      /> 
      </div> 

      <button type="submit" disabled={this.props.status === 'updating...'}>{btnText}</button> 
     </form> 
     <div>{this.props.status}</div> 
     </div> 
    ) 
    }; 
}; 



const mapStateToProps = (state) => { 
    return { 
    status: state.user.status 
    }; 
}; 

const mapDispatchToProps = (dispatch) => { 
    return bindActionCreators({apiUpdateUser}, dispatch); 
}; 

export default connect(
    mapStateToProps, 
    mapDispatchToProps 
)(EditUser); 

Une fois soumis, le code suivant (return {...state, status: action.msg}) est appelée dans la demande de api par dispatch mettre à jour le state qui met à jour la div cela montre le message d'erreur. Si je retourne juste ici state non modifié, le formulaire ne sera pas rendu comme prévu. Ce qui me perd est pourquoi le composant entier est re-rendu et pas seulement le div avec this.props.status. Ce que j'essaye de faire est d'empêcher le composant/forme de re-rendre quand il y a une erreur et status est mis à jour. Depuis status fait partie de state, lorsque la partie status de state change dans le réducteur, son re-rendu l'ensemble form au lieu de seulement le status div.

J'ai essayé d'ajouter key unique au form et au status div. J'ai essayé de faire le status div un composant séparé et en passant status comme props. J'ai essayé shouldComponentUpdate et la seule chose que j'ai pu faire pour éviter cela est de ne pas mettre à jour le statut dans l'état.

Comment puis-je empêcher le rendu du formulaire lors de la mise à jour de l'état? Est-ce que j'utilise redux-thunk et réagis mal?

Remarque comme une œuvre autour, j'ai ajouté this.state = {status: ''} au constructeur, a changé apiUpdateUser à une promesse et retiré de mapDispatchToProps. Sur la promesse résoudre je mets à jour le statut sur la page et si aucune erreur, j'appelle une action pour mettre à jour l'utilisateur puisque le re-rendu est ok si aucune erreur. Je ne suis pas sûr pourquoi ma méthode originale ne fonctionne pas comme prévu.

+1

Quel est le problème? En mappant l'état sur les accessoires, le composant sera mis à jour lorsque la valeur de l'état changera. L'algorithme de diffraction de React détermine ensuite, de manière performante, quels éléments doivent être mis à jour et lesquels peuvent rester les mêmes. Si vous le souhaitez, vous pouvez créer un composant d'état et mapper l'état des accessoires au sein de ce composant au lieu du formulaire. –

+1

"Si vous le vouliez, vous pouviez créer un composant d'état et mapper l'état des accessoires au sein de ce composant au lieu du formulaire", j'ai simplement fait quelque chose de similaire en testant différentes méthodes. Le 'problème' est lors de l'appel de setState à l'intérieur d'un composant, réagissent seulement met à jour les divs affectés comme prévu. Mais la mise à jour de l'état à partir du réducteur redux force toujours le composant entier à être rendu. – jtlindsey

Répondre

0

L'intégralité de votre composant EditUser est souscrit à un état Redux, lorsque l'état change, le composant entier sera ré-rendu. C'est ainsi que fonctionne le composant connecté. Si vous ne voulez pas que le formulaire entier soit rendu, vous pouvez simplement placer le bouton submit et le div sous le bouton dans un composant et faire du composant un composant connecté qui est abonné à l'état status, vous n'utilisez pas l'état dans d'autres endroits de toute façon.