Quiero evitar volver a renderizar mi componente secundario <ChildComponent/> cada vez que actualizo mi estado usando onClick en <ChildComponent/> . Tengo mi función de devolución de llamada en <ParentComponent/> que actualiza uno de los valores para el objeto de par clave-valor.
En el componente principal
const _keyValueObject = useMemo(() => utilityFunction(array, object), [array, object]) const [keyValueObject, setKeyValueObject] = useState<SomeTransport>(_keyValueObject) const handleStateChange = useCallback((id: number) => { setKeyValueObject(keyValueObject => { const temp = { ... keyValueObject } keyValueObject[id].isChecked = ! keyValueObject[id].isChecked return temp }) }, []) return( <Container> {!! keyValueObject && Object.values(keyValueObject).map(value => ( <ValueItem key={value.id} category={value} handleStateChange ={handleStateChange} /> ))} </Container> ) En componente secundario ValueItem
const clickHandler = useCallback( event => { event.preventDefault() event.stopPropagation() handleStateChange(value.id) }, [handleStateChange, value.id], ) return ( <Container> <CheckBox checked={value.isChecked} onClick={clickHandler}> {value.isChecked && <Icon as={CheckboxCheckedIcon as AnyStyledComponent} />} </CheckBox> <CategoryItem key={value.id}>{value.title}</CategoryItem> </Container> ) export default ValueItemEn el componente secundario, si uso la nota predeterminada de exportación (ValueItem), la casilla de verificación no se actualiza al hacer clic.
Lo que necesito ahora es no volver a renderizar cada componente secundario, pero teniendo en cuenta que la casilla de verificación funciona. ¿Alguna sugerencia?
Working Codesandbox Lo que debe hacer es envolver al niño con React.memo . De esta manera, se asegura de que Child se memorice y no se vuelva a procesar innecesariamente. Sin embargo, eso no es suficiente.
En padre, handleStateChange obtiene una nueva referencia en cada representación, por lo tanto, hace que la representación principal. Si el padre renderiza, todos los hijos volverán a renderizar. Envolver el handleStateChange con useCallback asegura que el componente de reacción recuerde la referencia a la función. Y memo recuerda el resultado para Child .
La propagación ( const temp = { ... keyValueObject } ) no clona en profundidad el objeto como podría pensar. Entonces, si bien keyValueObject tendrá una nueva referencia, sus valores de objeto no se clonarán, por lo que tendrán la misma referencia, por lo que memo pensará que nada cambia al comparar la category prop.
Solución: asegúrese de crear un nuevo valor para la identificación de keyValueObject que desea actualizar. Ejemplo: setKeyValueObject(keyValueObject => ({...keyValueObject, [id]: {...keyValueObject[id], isChecked: !keyValueObject[id].isChecked})) . Ahora keyValueObject[id] es un nuevo objeto/referencia, por lo que memo lo verá y representará su componente. No rendirá a los otros niños ya que sus referencias siguen siendo las mismas.