简体   繁体   中英

How to change pagination variables in react

I am working on building pagination. I'm still working on my API to fetch posts based on pagination, but at the moment I am stuck on a problem with states.

In my main file (where the posts will be), my code looks like this:

// Import modules
import React from "react";
import axios from "axios";
import url from "url";

// Import components
import { Snippet } from "../Snippet";
import { CreatePost } from "./CreatePost";
import { Pagination } from "./Pagination";

// Import styles
import "./css/Content.css";

// Axios Init
const api = axios.create({
    baseURL: `http://localhost:5000/api/`,
});

export class Content extends React.Component {
    state = {
        collections: [
            { title: "ReactJS", color: "red" },
            { title: "HTML", color: "cyan" },
            { title: "CSS", color: "pink" },
        ],
        snippets: [],
        limitSnippets: 3,
        page: 0,
    };

    constructor(props) {
        super(props);
    }

    componentDidMount() {
        this.getSnippets();
    }

    getSnippets = async () => {
        try {
            let data = await api
                .get(
                    `/snippets/fetchAll?limitSnippets=${this.state.limitSnippets}&page=${this.state.page}`,
                    {
                        body: {
                            limitSnippets: 3,
                            page: 1,
                        },
                    }
                )
                .then(({ data }) => data);
            this.setState({ snippets: data });
        } catch (error) {
            console.log(error);
        }
    };

    updatePagination = (page) => {
        this.state.page = page;
        console.log(this.state.page);
    };

    render() {
        return (
            <div className="content">
                <h1 className="content-header">Snippets</h1>
                <CreatePost contentUpdater={this.getSnippets} />
                <Pagination updatePagination={this.updatePagination} />
                <div className="w-layout-grid grid">
                    {this.state.snippets.map((snippet, i) => {
                        return (
                            <Snippet
                                key={i}
                                title={snippet.title}
                                code={snippet.code}
                                updatedDate={snippet.updatedDate}
                                createdDate={snippet.createdDate}
                                language={snippet.language}
                                creator={snippet.creator}
                                collections={snippet.collections}
                            />
                        );
                    })}
                </div>
                <Pagination />
            </div>
        );
    }
}
export default Content;

In pagination file, my code looks like this:

export const Pagination = (props) => {
    // States
    const [page, setPage] = useState(0);
    // Axios Init
    const api = axios.create({
        baseURL: `http://localhost:5000/api/`,
    });

    const handleLeft = (event) => {
        event.preventDefault();
        if (page > 0) {
            setPage(page - 1);
            props.updatePagination(page);
        } else {
            console.log("handleLeft(): page not > 0");
        }
        //props.updatePagination(page);
        //}
    };

    const handleRight = (event) => {
        event.preventDefault();
        // page < fetchAllPages
        setPage(page + 1);
        props.updatePagination(page);
    };

    /*useEffect(() => {
        props.updatePagination(page);
    }, [page]);
*/
    return (
        <div className="paginate-div">
            <div className="paginate-next">
                <div className="paginate-next-icon" onClick={handleLeft}>
                    <i className="fas fa-caret-left"></i>
                </div>
            </div>
            <a href="#" className="paginate-button first w-inline-block">
                <div className="paginate-text">1</div>
            </a>
            <a href="#" className="paginate-button w-inline-block">
                <div className="paginate-text">2</div>
            </a>
            <a href="#" className="paginate-button w-inline-block">
                <div className="paginate-text">3</div>
            </a>
            <a href="#" className="paginate-button w-inline-block">
                <div className="paginate-text">4</div>
            </a>
            <a href="#" className="paginate-button w-inline-block">
                <div className="paginate-text">5</div>
            </a>
            <a href="#" className="paginate-button w-inline-block">
                <div className="paginate-text">6</div>
            </a>
            <a href="#" className="paginate-button last w-inline-block">
                <div className="paginate-text">...</div>
            </a>
            <div className="paginate-next" onClick={handleRight}>
                <div className="paginate-next-icon">
                    <i className="fas fa-caret-right"></i>
                </div>
            </div>
        </div>
    );
};

I have my pagination component which is passed a prop thats a function to updatePagination(). The pagination component has functions for left and right button for switching thru pagination, and when it is clicked, the main file gets the pagination updated.

The problem I am having (SORRY IF CONFUSING BY THE WAY I WORDED THIS) The default page is 0 (which is basically page 1). The crazy thing is when I press right (handleRight is called on submit), it stays at page 0, then if I click it again it goes to 1, then after if I press the left button (which called handleLeft on submit) while it is on page 1, it goes up to 2 somehow, but if I click it again it goes back down to 1, then if I click again it goes to 0.

Why is this strange problem occuring?? Please help me ASAP

setPage is asynchronous, so when you setPage to decrement and then immediately call props.updatePage , props.updatePage is receiving the old value of page . You can read all about this common problem here .

const handleRight = (event) => {
        event.preventDefault();
        // Hey React, set page to page + 1 and rerender the component
        setPage(page + 1);
        // But before you do that, call props.updatePagination on the old value
        props.updatePagination(page);
    };

You should ask yourself, though, why you even store two stateful values of page at all (one in the parent component, one in the child component). Couldn't the Content component keep track of your page state (as it already does) and pass it down as a prop, getting rid of your need for a page state in the child component? This is called Lifting State Up , and it's a fundamental concept in React, which incentivizes you to use the least amount of state possible to avoid exactly this kind of desync. Furthermore, from the code you've shared, the Pagination component just displays the page numbers - why does it even need to be stateful at all?

The problem was that the old value of page was being used in updatePagination(), I fixed this by not running updatePagination(page) in the same place, I used useEffect(), and checked for changes to {page}, and ran updatePagination in there.

useEffect(() => {
    props.updatePagination(page);
}, [page]);

The handleLeft, handleRight functions were changed to look like this:

const handleLeft = (event) => {
        event.preventDefault();
        let newPage = page - 1;
        if (page > 0) {
            setPage(newPage);
        } else {
            console.log("handleLeft(): page not > 0");
        }

        //}
    };

NOTE" In the comments section, someone made a point that I should not be storing the page number in two places, but rather store them in one place and pass it over as props. I have not currently tried to do this , but I plan on doing this soon. But for now, this is the best answer for this scenario.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM