ayxos
ayxos

Reputation: 408

React + Redux Update issue

I have this class:

  import React from 'react';
  import {Link} from 'react-router';
  import '../../styles/about-page.css';
  import Item from './Item';
  // Redux
  import { connect } from 'react-redux';
  import actions from '../../redux/actions';
  import { bindActionCreators } from 'redux';
  // Auth
  import Auth from '../../modules/Auth';
  import User from '../../constants';

  class CommentForm extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        value: ''
      };
    }

    handleChange(event) {
      this.setState({value: event.target.value});
    }

    handleSubmit() {
      // alert('A name was submitted: ' + this.state.value);
      this.props.onFinish({
        name: this.props.user.name,
        userId: this.props.user.id,
        comment: this.state.value
      });
    }

    render() {
      if (!this.props.user || !this.props.user.name) return <div/>;
      return (<div className="item"> 
        {this.props.user.name}: 
        <label style={{width: '60%', margin: '10px'}}>
          <input style={{width: '100%'}} type="text" value={this.state.value} onChange={this.handleChange.bind(this)} />
        </label>
        <input style={{width: '16%', display: 'inline-block', margin: '10px'}} type="submit" value="Enviar" onClick={this.handleSubmit.bind(this)}/>
      </div>
      );
    }
  }

  @connect((state) => state)
  class ItemPage extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        user: null,
        pret: null
      };
    }

    componentWillMount() {
      let self = this;
      this.props.actions.getPret(this.props.routeParams.id).then(function(a) {
        self.setState({
          pret: self.props.pret
        })
      });
      if (Auth.isUserAuthenticated()) {
        User.getBearer(Auth, function(info) {
          self.setState({user: info});
        });
      }
    }

    onFinish(comment) {
      //changing the state in react
      //need to add '6' in the array

      //create a copy of this.state.a
      //you can use ES6's destructuring or loadash's _.clone()
      const currentStatePretCopy = Object.assign({}, this.state.pret, { b: this.state.pret.comments.concat([comment])})
      console.log(1, currentStatePretCopy);
      currentStatePretCopy.comments.push(comment);
      this.props.actions.updatePret(currentStatePretCopy);
    }

    render() {
      let self = this;
      if (!this.state || !this.state.pret) return <div/>;
      return (<div>
        <section>
          <Item full={true} user={this.state.user} item={this.state.pret} actions={this.state.actions}/>
        </section>
        <div>
          <CommentForm user={this.state.user} pret={this.state.pret} onFinish={this.onFinish.bind(this)}/>
          {/* TODO: ad here */}
          {this.state.pret.comments && this.state.pret.comments.length ? this.state.pret.comments.map(function (comment, index) {
            return (<div className="item" key={index}> by <Link to={'/user/' + comment.userId}> @{comment.name} </Link> : {comment.comment} </div>);
          }) : null}
        </div>
      </div>
      );
    }
  }

  function mapStateToProps (state) {
    return {
      pret: state.prets[0]
    };
  }

  function mapDispatchToProps (dispatch) {
    return {
      actions: bindActionCreators(actions, dispatch)
    };
  }

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

When i want to update the object, since props should be immutable, the documentation suggest cloning the object and put it in the state.

I am modifying the state with the new value and sending it to Redux actions but the system complains:

Uncaught Error: A state mutation was detected between dispatches, in the path 'prets.0.comments.1'. This may cause incorrect behavior.

Since i copy the object I do not know how should I update the store via React+Redux

Upvotes: 0

Views: 105

Answers (1)

Lorenzo Natali
Lorenzo Natali

Reputation: 51

The comments array is still the original one. So you are mutating the original object with push. Replace

currentStatePretCopy.comments.push(comment);

With

currentStatePretCopy.comments = currentStatePretCopy.comments.concat([comment])

And everything should work fine

Upvotes: 1

Related Questions