简体   繁体   中英

How can I cache component data in React so it doesn't re-render on every load?

I am using React native and on one of my screens I have a toggle component. The component has 2 options and clicking on them renders different data. I've noticed performance is not bad on ios but awful on Android and I want it to be good on both (obviously)

The props and state are not changing every time I toggle so it should just be able to render it super fast? the second screen is where I'm seeing more of an issue. but is essentially a fairly big array, rendering a list with lists inside each one.

I've tried using this: export const CachedPreviousGames = React.memo(PreviousGames) where PreviousGames is the component in question

However, when I toggle back and forth I see that the component console.logs are fired, I also see the console.logs inside the .map functions are called. is this expected? I was hoping React.memo would only re-render if the props changed?

Is there any other caching strategy I can do to fix this to make it more performant?

MORE DETAILS

so the two components are League and Previous Games where I'm basically mapping over data from my redux store in League and in Previous Games it takes a prop of games and maps over that. it's quite an expensive function, verified by the fact that when I replace the map with just a Text string, the toggle appears to happen much faster. When I say props don't change I mean, exactly that. Previous Games loads up with fresh data on app load but it never changes (until this happens again). ie every time I toggle, the props remain constant

If you need more control on when to skip render using React.memo , you should write a custom compare function. You can write your own custom function to do comparison or use from some library like isEqual from lodash.

React.memo will skip re-render when props are same ie shallow equal .

If your component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result.

React.memo only checks for prop changes. If your function component wrapped in React.memo has a useState, useReducer or useContext Hook in its implementation, it will still rerender when state or context change.

By default it will only shallowly compare complex objects in the props object. If you want control over the comparison, you can also provide a custom comparison function as the second argument.

Default behavior (shallow compare)

Example, Child and Parent both are re-rendering even when values are "same":

 const ChildMemo = React.memo(Child) function Parent() { console.log('parent rendering...') const [value, setValue] = React.useState([1]) return <ChildMemo value={value} setValue={setValue} /> } function Child({ value, setValue }) { console.log('child rendering...') return <button onClick={() => setValue([1])}>{JSON.stringify(value)}</button> } ReactDOM.render(<Parent />, document.getElementById('myDemoDiv'))
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script> <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> <body> <div id="myDemoDiv"></div> </body>

Custom behavior (custom/deep compare):


Example, Child is not rendering when values are "same":

 const ChildMemo = React.memo(Child, (prevProps, props) => { return _.isEqual(prevProps.value, props.value) }) function Parent() { console.log('parent rendering...') const [value, setValue] = React.useState([1]) return ( <ChildMemo value={value} setValue={setValue} /> ) } function Child({ value, setValue }) { console.log('child rendering...') return ( <button onClick={() => setValue([1])}>{JSON.stringify(value)}</button> ) } ReactDOM.render(<Parent />, document.getElementById('myDemoDiv'))
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script> <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> <body> <div id="myDemoDiv"></div> </body>

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