简体   繁体   中英

Correct Way to Transfer Props to State (if needed) React & Redux

I have created a Create-React-App react app & Redux.

I am using connect to map my userReducer to state (via mapStateToPrope) ie:

function mapStateToProps({ userProfile }) {
return { userProfile: userProfile ? userProfile : null };
}

export default connect(mapStateToProps, fetchUserProfile)(Profile);

and I have an input which I have binded the UserProfile Firstname to:

render(){
   return (
    <div>
       <input type="text" value={this.props.userProfile.firstName} />
   </div>
 ) 
}

This issue is now that I have it binded to the props, I am unable to change it, If I type in the input it wont change the text inside the input..

If I add a onChange={updateValue} method, and try and update the prop it wont work as a component can not update its own props.

So that leaves Transfering the props to state.

constructor(props){
    super(props);
    this.state = { FirstName : this.props.userProfile.firstName }
}

is this the recommended way to get an initial value from props?

You are trying to use a controlled input without providing information about updating the state.

If you just want to provide an initial state, you could use the defaultValue property of input fields.

<input defaultValue={this.props.value} />

With this you could easily change the input value, without writing overhead.

However, if you want to update your component, you should use the component state (like you did in your onChange example) or you use the redux state, if you want to provide the input value to more components than your input component.

const Component = ({ firstname, updateFirstname }) => (
  <input
    onChange={updateFirstname}
    value={firstname}
  />
);

const mapStateToProps = state => ({
  firstname: state.profile.firstname,
});

const mapDispatchToProps = dispatch => ({
  updateFirstname: e => dispatch({ type: 'UPDATE_FIRSTNAME', firstname: e.target.value }),
});

connect(mapStateToProps, mapDispatchToProps)(Component);

In order to have a change take place managed in either local state or redux, you want to call the function onChange as follows

onChange={(e) => this.updateField('fieldName',e.target.value,e)}

The value field would be and would always be updated when the props (or state are updated)

value={this.props.fieldName}

or

value={this.state.fieldName}

You onChange function would either call setState({fieldName: value}) to set local state or dispatch to redux to update the Store which is turn would update the local state via your mapStateToProps function.

There's nothing wrong in doing that for a controlled component. But one mistake you made is there is no this.props in the constructor. You're passing props directly to the constructor using the props variable. So the code will be

this.state = {
  FirstName: props.userProfile.firstName
};

But if you want the value from the store to be updated on the component later on then do declare componentWillReceiveProps() and set the state value there also so that the changes in store are captured here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM