React - changing key prop doesn't cause rerender of child component

Viewed 3290

I am using react-infinite-scroll to render a feed of data. Whenever the user changes their settings, I want to refresh the feed of data.

To do this, I have a key prop for the InfiniteScroll component. The idea being whenever the user changes their settings

  1. this.state.renderCount is incremented by 1 in setState
  2. React notices that the key prop of InfiniteScroll is different, and re-renders the component from scratch.

      <Content style={{ padding: "0px 20px" }}>
        <InfiniteScroll
          key={this.state.renderCount}
          style={{ width: "100%", height: "100%" }}
          pageStart={0}
          loadMore={this.loadPosts.bind(this)}
          hasMore={true}
          loader={<div>Loading....</div>}
          useWindow={false}
        >
          {listItems}
        </InfiniteScroll>
      </Content>
    

The refresh code is in componentDidUpdate and is called if I determine that a refresh is needed:

  this.setState({ renderCount: this.state.renderCount + 1 })

However, the component is not reset. Why is this?

2 Answers

key and ref are special keywords in react. See

Most props on a JSX element are passed on to the component, however, there are two special props (ref and key) which are used by React, and are thus not forwarded to the component.

For instance, attempting to access this.props.key from a component (i.e., the render function or propTypes) is not defined. If you need to access the same value within the child component, you should pass it as a different prop (ex: <ListItemWrapper key={result.id} id={result.id} />). While this may seem redundant, it’s important to separate app logic from reconciling hints.

To pass they key prop to the child element use another name.

See also : Why is ref not a property in children components?

Turns out I was overthinking it.

With the way react-infinite-scroll works, I just have to clear the listItems array.

In my case, I just had to do:

  this.setState({ templates: [] })

(listItems is generated by a map function that maps templates to jsx).

Related