Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React component not re-rendering after props change

I am trying to filter a set of objects in the state whenever the user clicks on a button on my component. The logic of the filtering works fine, but when it gets back to the component, the filtered objects are missing and instead the property is undefined. Am I missing a lifecycle method?

The click event:

<div onClick={this.filterMyPosts}>My Posts</div>
...
<div>
    {this.renderPosts()}
</div>

filterMyPosts

filterMyPosts() {
   this.props.updateFilter("myPosts");
   // filtering function uses switch statement based on strings to filter posts
}

The component container:

const mapStateToProps = (state) => {
  return {currentUser: state.session.currentUser,
    posts: allPostsByFilter(state.posts, state.filter, state.session.currentUser.id, state.bookmarks)}
};

const mapDispatchToProps = (dispatch) => ({
  updateFilter: (filter) => dispatch(updateFilter(filter))
})

The filtering takes place in a different file, which returns the filtered events in an object. That logic has no errors.

The problem: By the time it gets to the following function, "posts" is undefined. So somewhere along the way, the filtered posts are not making it back to the component.

renderPosts() {
    return (
    <div className ="user-profile-posts">
      <ul>
       {Object.keys(this.props.posts).map(id => <PostIndexItem 
        key={`posts-index-item${id}`} 
        post={this.props.posts[id]}
        user={true}
        />)}
      </ul>
    </div>
    );
  }

EDIT - filter function

export const allPostsByFilter = (filter, currentUserId, posts) => {
  switch (filter) {
case "myPosts":

  let postKeys = Object.keys(posts).filter( (id) => {
    return(posts[id].user_id === currentUserId)
  });
  let userPosts = {}
  postKeys.forEach( (key) => userPosts[key] = posts[key])
  let newPosts = {}

  let postKeys = Object.keys(posts).filter( (id) => {
    return (Object.keys(userPosts).includes(id))
  });
  eventKeys.forEach( (key) => newPosts[key] = posts[key])

  return newPosts

default: 
      return posts
like image 716
Marc Fletcher Avatar asked Sep 04 '16 03:09

Marc Fletcher


People also ask

Do components re-render when props change?

Props are not affected by the state change, so heavy components won't re-render.

Will React component update if props change?

By default, when your component's state or props change, your component will re-render. If your render() method depends on some other data, you can tell React that the component needs re-rendering by calling forceUpdate() .

How do you make a component render again in React?

The forceUpdate() method With this method we will achieve the long-awaited forced rendering of a React component. Calling forceUpdate() will cause the component to be rendered to be called and shouldComponentUpdate() will be skipped.

How do you're-render React component after state change?

React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.


1 Answers

You lose this context when binding your action.

<div onClick={this.filterMyPosts}>My Posts</div>

Change the invocation to

<div onClick={() => this.filterMyPosts()}>My Posts</div>

This assures this in your filterMyPosts method. Without it, props is undefined.

like image 124
Mario Tacke Avatar answered Sep 20 '22 07:09

Mario Tacke