Search code examples
javascriptreactjsreact-hookspaginationmemoization

How to memoize a component or its result if its getting used twice on same parent component?


I have a parent component which is displaying files. At the top and bottom of that files section, there is a pagination component.

ParentComponent.jsx

export default function ParentComponent(){
    .
    .
    .
    const FilesPaginationComp = (
        <Pagination
          totalCount={totalFileCount}  //Number
          perPageCount={perPageFiles}  //Number
          currentPage={currentPage}    //Number
          changePage={setCurrentPage}  //setState function from useState hook
          offset={7}
        />
    );      
    return(
    <>
        {FilesPaginationComp}
        {files}
        {FilesPaginationComp}
    </>
    )
}

Pagination.jsx

export default function Pagination(props){
    .        //dont have any state (pure function)
    .
    .
    console.log('in pagination');   //its getting printed twice
    const paginationBtns=....
    return paginationBtns;
}

Since the Pagination component has the same props 2nd time, I am expecting it should not directly compute pagination values again. (print that log only once).

I have tried the below-mentioned scenarios but they didn't work for me.

  1. using memo

Pagination.jsx

export default memo(function Pagination(props){
    .        //dont have any state (pure function)
    .
    .
    console.log('in pagination');   //its getting printed twice
    const paginationBtns=...;
    return paginationBtns;
})
  1. memo with useMemo in pagination

Pagination.jsx

export default memo(function Pagination(props){
    //dont have any state (pure function)
    const paginationBtns=useMemo(()=>{
      console.log('in pagination');   //its getting printed twice
      .
      .
      .
      return final_result;
    },[...props]);
    return paginationBtns;
})
  1. along with memo and useMemo in Pagination.jsx, useMemo in parent component

ParentComponent.jsx

export default function ParentComponent(){
    .
    .
    .
    const FilesPaginationComp = useMemo(()=>(
        <Pagination
            totalCount={totalFileCount}  //Number
            perPageCount={perPageFiles}  //Number
            currentPage={currentPage}    //Number
            changePage={setCurrentPage}  //setState function from useState hook
            offset={7}
        />
    ),[totalFileCount,perPageFiles,currentPage]);
    return(
    <>
        {FilesPaginationComp}
        {files}
        {FilesPaginationComp}
    </>
    )
}

Pagination.jsx

export default memo(function Pagination(props){
    //dont have any state (pure function)
    const paginationBtns=useMemo(()=>{
        console.log('in pagination');   //its getting printed twice
        .
        .
        .
        return final_result;
    },[...props]);
    return paginationBtns;
})

Am I missing anything or is there any other good way to achieve this?

Edit: Adding sandbox link for reference. https://codesandbox.io/s/react-pagination-ymiwz


Solution

  • export default memo(function Pagination(props) {
        const paginationBtns=useMemo(()=>{
          console.log('in pagination');
          return final_result;
        },[...props]);
        return paginationBtns;
    })
    

    When Pagination is used twice in the parent component, two paginationBtns will be created because each Pagination will have its instance of paginationBtns.

    You can calculate and memoize the value in the parent component and send it as props to Pagination.

    example:

    const Memoized = memo(({ children }) => {
      return children;
    });
    
    export default function App() {
      const expensive = useMemo(() => {
        console.log("here");
        return "hi";
      }, []);
    
      return (
        <div className="App">
          <h1>Hello CodeSandbox</h1>
          <h2>Start editing to see some magic happen!</h2>
          <Memoized children={expensive} />
          <Memoized children={expensive} />
        </div>
      );
    }
    

    Edit practical-ully-p9j37