Verhulstd
Verhulstd

Reputation: 301

How to avoid useless rerender using useReducer([state,dispatch]) and useContext?

When using multiple useReducers every component using a part of the state rerenders.

import React, { useContext } from 'react'
import Store from '../store'
import { setName } from "../actions/nameActions"

const Name = () => {
    const { state: { nameReducer: { name } }, dispatch } = useContext(Store)
    const handleInput = ({ target: { value } }) => { dispatch(setName(value)) }
    console.log('useless rerender if other part (not name) of state is changed'); 
    return <div>
        <p>{name}</p>
        <input value={name} onChange={handleInput} />
    </div>
}

export default Name;

How to avoid this useless rerendering?

Upvotes: 11

Views: 12932

Answers (1)

Estus Flask
Estus Flask

Reputation: 222419

If useState or useReducer state changes, the component is updated, there is no way to prevent this in the component itself.

Re-render should be prevented in child component that depends on partial state, e.g. by making it pure:

const NameContainer = () => {
    const { state: { nameReducer: { name } }, dispatch } = useContext(Store)
    return <Name name={name} dispatch={dispatch}/>;
}

const Name = React.memo(({ name, dispatch }) => {
    const handleInput = ({ target: { value } }) => { dispatch(setName(value)) }
    return <div>
        <p>{name}</p>
        <input value={name} onChange={handleInput} />
    </div>
});

NameContainer can be rewritten to a HOC and serve the same purpose as Redux connect, to extract needed properties from a store and map them to connected component props.

Upvotes: 16

Related Questions