1

The current state object is this:

this.state = {
        loadedPostList: [],
        top: 0,
        end: 0,
        thresh: 20,
        page: 0,
        loadingPostList: false,
        filter: [],
        lazying: false
};

I'm utilising some react lifecycle methods to control my redux store updates, and dataflow:

shouldComponentUpdate(nextProps, nextState) {
    return this.props.posts.loadedPosts !== nextProps.posts.loadedPosts || this.state.loadedPostList !== nextState.loadedPostList;
}

componentDidUpdate(prevProps) {
    let { loadedPosts, changeEvent, updatedId, deleteId } = this.props.posts;
    if(prevProps.posts.loadedPosts !== loadedPosts) {

        switch(changeEvent) {
            case 'insert':
                if(this.state.top === 0) {
                    this.refreshList();
                }
                console.log('new post in thread...');
                break;
            case 'update':
                this.refreshList();
                console.log('post updated in thread...');
                break;
            case 'delete':
                this.refreshList();
                console.log('post deleted in thread...');
                break;
            default:
                break;
        }
    }
}

refreshList = () => {
    let newList = this.props.posts.loadedPosts.slice(this.state.top, this.state.end);
    this.setState({
        loadedPostList: [...newList]
    }, () => {
        console.log('refreshed post list')
    })
}

And in the render function, I'm mapping the elements of this.state.loadedPostList to PostList components. The problem is that when my redux store updates, and subsequently my this.state.loadedPostList, the mapping in re-render doesn't update to show the updated array. Logging to the console and observing the redux actions and store via redux dev tools show that the array is indeed updating correctly, and the functions such us refreshList() are working as they should. However, the problem remains with the DOM not re-rendering/updating according to the state changes. The render function:

render() {
    return (
        <div id="question-list-wrapper">
            {
                this.state.loadingPostList || this.state.lazying ? 

                <MiniViewLoader textToRender="Loading questions..."/>

                :


                <div id="question-list-inner-wrapper">

                    <div id="question-list-inner-wrapper-nav">
                        <h1 className="text" id='inner-wrapper-nav-header'> Recent Questions </h1>
                    </div>
                    {
                        this.state.loadedPostList.length < 1 ?  <h1 className="no-questions-text">No questions availabe</h1> : ""
                    }
                    {
                        this.state.loadedPostList.map((post, index) => {
                            return (
                                <PostSlot idx={index} key={index+""} postData={post}/>
                            )
                        })
                    }

                    <div id="question-list-write-btn" alt="Ask Question">
                        <span>Ask Question</span>
                        <WritePostButton />
                    </div>

                </div>


            }
        </div>
    )
}

(EDIT) Further information if it helps. The component with the issue is being rendered by a react router Switch wrapper inside the render() function of another component.

The Other Component:

render() {

    return(
        <div className="page-wrapper">
            {
                this.state.settingUp ?

                <FullPageLoaderWithText textToRender="Setting things up for you..."/>
                :

                <div id="main-hoc-wrapper-inner-wrapper">

                    <div id="main-hoc-nav-bar" className="item-a">
                        <span id="main-hoc-nav-logo" className="main-hoc-nav-elem">
                            PA
                        </span>
                        <span id="main-hoc-nav-search" className="main-hoc-nav-elem">
                            <input type="text" placeholder="Search..." className="placeholderEdit"/>
                        </span>
                    </div>

                    <div id="main-hoc-sidebar" className="item-c">
                        <span className="main-hoc-sidebar-tabs">{this.props.user.data}</span>

                        <span className="main-hoc-sidebar-tabs">tags</span>

                        <span className="main-hoc-sidebar-tabs">community</span>

                        <span className="main-hoc-sidebar-tabs">opportunities</span>
                    </div>

                    <div id="main-hoc-main-view" className="item-b">
                        <Switch>
                            {/* <Route path="/:param1/:param2/path" component={QuestionList} /> */}
                            <Route path="/:param1/:param2/path" render={() => <QuestionList connect={socket}/>} />

                        </Switch>
                    </div>

                    <div id="main-hoc-right-bar" className="item-d">
                        Blog posts & ads
                    </div>

                </div>
            }


        </div>
    )
}
williamcodes
  • 340
  • 4
  • 18

2 Answers2

1

I think the problem is your if condition, you cannot compare two array with !==.

Example:

var t = [1,2,3];
var f = [1,2,3];

if (t !== f) {
  console.log("different");
} else {
  console.log("same");
}

// by your logic the output should be "same"
// but it will not be
// because internally they both are object and we cannot compare
// two objects using `===` operator.
// you will have to loop through and check for difference


// or better let REACT HANDLE SUCH THINGS

Sagar More
  • 466
  • 2
  • 8
0

the problem is in this line

let newList = this.props.posts.loadedPosts.slice(this.state.top, this.state.end);,

this.state.top and this.state.end is both 0, so it will always return an empty array, make sure you are updating the top and end after each refresh.

Hemanath
  • 1,075
  • 6
  • 15
  • this.state.top and this.state.end are working fine; the refresh function doesn't actually refresh the page/list; its merely deciding if the updated part of the greater list, is in the scope (index range) of top, and end. The array is updated correctly after the refresh function runs (I've verified this via console logging, and observing the state changes in the redux dev tools). The problem is that the ui in render thats mapping the elements of this array, does not re render or update, even after the elements in the array change (not unless the page is manually refreshed). – williamcodes Mar 19 '20 at 07:31