pedalpete
pedalpete

Reputation: 21536

mixing state in component with redux

I've got a component which takes a list from my apps state, and I want to filter that list based on the input of a text field in the component. When the user filters the list they can then select an item from the list and that will update the state.

It seems to me that having the filter as part of the apps state is not valuable, as the filter itself is only needed for this component.

My redux state is

onst mapStateToProps = (state) => {
    return {
        tracks: Object.keys(state.activities).map(a => {
            return {
                id: state.activities[a].id,
                user: state.activities[a].user,
                color: state.activities[a].color
            }})
    };
}

const mapDispatchToProps = (dispatch) => {
  return {
        setTarget: (targetId) => {
            dispatch(setTargetPointsById(targetId))
        }
    }
};

const TrackSelectorControl = connect(mapStateToProps, mapDispatchToProps)(TrackSelector);

export default TrackSelectorControl;

and then in my component, I have

lass TrackSelector extends Component {
  componentWillMount() {
     this.setState({filter: false})
  }
  componentWillReceiveProps(props, state) {

  }
  componentDidUpdate(props, state) {
  }
  shouldComponentUpdate() {
    return false;
  }
  filter() {
      if (!this.state.filter) return this.props.tracks
      return this.props.tracks.filter(t => {
         return t.user.name.includes(this.state.filter)
      })
  }
  render() {
    return <ul className={style.list}>
            <input type="text" placeholder="Filter" onChange={(evt) => {
                this.setState({filter: evt.target.value});

            }} />
            {this.filter().map(track => {
            return <li key={track.id} onclick={this.props.setTarget(track.id)} className={style.track}>
                        <img style={{borderColor: createColor(track.color) }} src={track.user.avatar} className={style.img} />
                        <span>{track.user.name} </span>
                    </li>
            })}
        </ul>
    }
}

export default TrackSelector;

The error I get is warning setState({...}) cannot update...

Upvotes: 1

Views: 513

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 281686

You are getting this error because when you write

<li key={track.id} onclick={this.props.setTarget(track.id)} className={style.track}>

you are calling the setTarget function onClick but since you are calling it like

onclick={this.props.setTarget(track.id)}

it means that onClick is assigned a value and not a function since it takes the return value of this.props.setTarget(target.id).

So everytime your component renders this function will be called automatically without the event to fetch the value and since you are setting a state in that function you are getting a warning.

You need to bind this function like

 onclick={this.props.setTarget.bind(this, track.id)}

and it will solve the problem

Upvotes: 1

Related Questions