Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force dom re render in react

Tags:

reactjs

I am trying to force a child component to re-render. I have tried this.forceUpdate();, but it does not work. I put console.log statements in my <PostList /> component, and none of them are ever called--not componentDidMount, nor componentWillMount, componentWillReceiveProps, none of them. It's as if the <PostList /> component is never initialized. I am sure it is though, because I know for a fact items.count retrieves my items. Here is my render method:

 render() {
        const items = this.state.posts;
        const postList = items.count > 0 ? (<PostList comingFromSearch={true} xyz={items} />) : (<div></div>)
        const navBar = <NavigationBar />
        return (
                <div><br/>{navBar}
                   <div className="container">
                     <h3>Search Results for {this.state.searchTerm}</h3>
                        <div className="row">
                            <div className="col-x-12">{postList}</div>
                        </div>
                   </div>
                </div>
            )
     }

And here is my api call:

    retrieveSearch(term) {
        Helpers.searchWithTerm(term).then((terms) => {
                const postsWithTermsInTitle = terms.titleResults
                this.setState({posts: postsWithTermsInTitle})
                this.forceUpdate();
        }).catch((error) => {   
                console.log("error searching: " + error);
        })
   }

I should note, on my previous page, i had another ` component, and maybe react is using that one instead of this one? I want to force it to use this instance.

If this.forceUpdate(); does not make the whole DOM re-render, how can I do that?

thanks


1 Answers

your PostList and NavigationBar Components might not update because they only update when their props are changed (shallow compare).

PostList might not update when changing the inner content of the array, because the component will shallow compare the new state with the previous one. Shallow comparing an array will basically checked against its length property. which does not change in this case.

Quick Solution

Sometimes you need to update a List, without changing any of its props or the length of the list. To achieve this, just pass a prop to the component and keep incrementing it instead of calling force update.

retrieveSearch(term) {
    Helpers.searchWithTerm(term).then((terms) => {
            const postsWithTermsInTitle = terms.titleResults
            this.setState((curState) => ({posts: postsWithTermsInTitle, refreshCycle: curState.refreshCycle+1}))
            this.forceUpdate();
    }).catch((error) => {   
            console.log("error searching: " + error);
    })

}

 render() {
     ...
     <PostList
        ...
        refreshCycle={this.state.refreshCycle}
     />
     ...
 }

Right solution

The right solution is to provide an itemRenderer which you is a function that returns the an individual item from the list. This function is passed as a prop to the component.

This way you have control over how the items inside the list will appear, also changes inside the itemRenderer function will cause a component update.

 itemRenderer(itemIndex) {
    return <div>{this.props.item[itemIndex]}</div>;
 }
 render() {
    ...
    <PostList
       itemRenderer={this.itemRenderer.bind(this)}
       itemsLength={items.length}
    />
    ...
 }

The itemRenderer will be called inside the PostList in a loop (of length itemsLength). each loop will be passed the index of the current iteration, so you can know which item of the list to return from the function.

This way you can also make your list more scalable and more accommodating.

You can check an implementation of such solution on a list package like this one: https://www.npmjs.com/package/react-list

like image 157
Bamieh Avatar answered Feb 01 '26 19:02

Bamieh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!