Annah Isenberg
Annah Isenberg

Reputation: 157

Creating custom pagination, but next and prev buttons are not working

I'm trying to create my own pagination (without using a package), but I can't get it to work.

I'm wondering if it has something to do with how I'm copying my arrays, but I'm not really sure.



class InsightSearchResults extends Component {
    state = {
        start: 0,
        end: 2,
        insightsArrayOriginal: [],
        copiedArr: []
    }

    UNSAFE_componentWillReceiveProps(nextProps) {
        if (nextProps.insightList[0]) {
            this.setState({
                insightsArrayOriginal: nextProps.insightList[0].insights,
                copiedArr: nextProps.insightList[0].insights.splice(this.state.start, this.state.end)
            })
        }
    }


    clickNext = () => {
        let copied = [...this.state.insightsArrayOriginal];

        this.setState({
            start: this.state.start + 2,
            end: this.state.end + 2
        }, () => {
            this.setState({
                copiedArr: copied.splice(this.state.start, this.state.end)
            })
        })
    }


    clickPrev = () => {
        this.setState({
            start: this.state.start - 2 < 0 ? 0 : this.state.start - 2,
            end: this.state.end - 2
        })
    }

    render() {
        const { copiedArr } = this.state;

        return (
            <div style={{padding: "1.5rem"}}>

                {copiedArr ? copiedArr.map(insight => (
                     <div>
                     <Grid className="insight_result_block">
                        <Col className="insight_results_col2" span="10">
                            <div>
                              <h4>Hello</h4>
                                <p>{insight.insightDesc}</p>
                           </div>
                        </Col>
                     </Grid>
                     <hr className="bottom_hr_insight" />
                     </div>
                )) : <p>loading...</p> }

                <button onClick={this.clickPrev}>Prev</button>
                <button onClick={this.clickNext}>Next</button>
            </div>
        )
    }
}


I haven't really worked on the "prev" part yet. I'm just trying to get the "next" to work for now...

Upvotes: 2

Views: 1515

Answers (1)

Istvan Szasz
Istvan Szasz

Reputation: 1567

There are two problems:

  1. UNSAFE_componentWillReceiveProps is not called on initial render. From the docs:

React doesn’t call UNSAFE_componentWillReceiveProps() with initial props during mounting. It only calls this method if some of component’s props may update. Calling this.setState() generally doesn’t trigger UNSAFE_componentWillReceiveProps().

  1. splice mutates the original array, use slice instead. See this question.

So you can move the content of UNSAFE_componentWillReceiveProps to componentDidMount and componentDidUpdate

componentDidMount() {
    this.updateState();
}

componentDidUpdate() {
    // check if a change in props has caused the rerender
    // or you will get infinite rerenders if one state update causes the next one
    if (
      this.props.insightList[0] &&
      this.props.insightList[0].insights !== this.state.insightsArrayOriginal
    ) {
      this.updateState();
    }
}

These functions don't receive a parameter: replace nextProps parameter with this.props; and change all splice occurrences with slice.

updateState() {
    if (this.props.insightList[0]) {
      this.setState({
        insightsArrayOriginal: this.props.insightList[0].insights,
        copiedArr: this.props.insightList[0].insights.slice( .     // <-here
          this.state.start,
          this.state.end
        )
      });
    }
}

clickNext = () => {
    let copied = [...this.state.insightsArrayOriginal];
    this.setState({ start: this.state.start + 2, end: this.state.end + 2 },
      () => {
        this.setState({
          copiedArr: copied.slice(this.state.start, this.state.end)  // <- and here
        });
      }
    );
};

Also, based on this code sample alone, you could entirely remove insightsArrayOriginal from your state and use it from props, but this may change if you plan to expand the functionality.

Upvotes: 1

Related Questions