Tengo un componente de botón que tiene un botón dentro que tiene un estado que se le pasa isActive y una función de clic. Cuando se hace clic en el botón, el indicador isActive cambiará y, dependiendo de eso, la aplicación obtendrá algunos datos. El componente principal del botón no se vuelve a representar. He buscado cómo forzar la detención de la reproducción de un componente y descubrí que React.memo(YourComponent) debe hacer el trabajo, pero aún no funciona en mi caso. También tiene sentido pasar una función de verificación para la función memo, ya sea para volver a procesar o no, que establecería en falso todo el tiempo, pero no puedo pasar otro argumento a la función. Ayuda.
botón.tsx
interface Props { isActive: boolean; onClick: () => void; } const StatsButton: React.FC<Props> = ({ isActive, onClick }) => { useEffect(() => { console.log('RERENDER'); }, []); return ( <S.Button onClick={onClick} isActive={isActive}> {isActive ? 'Daily stats' : 'All time stats'} </S.Button> ); }; export default React.memo(StatsButton);padre.tsx
const DashboardPage: React.FC = () => { const { fetchDailyData, fetchAllTimeData, } = useDashboard(); useEffect(() => { fetchCountry(); fetchAllTimeData(); // eslint-disable-next-line }, []); const handleClick = useEventCallback(() => { if (!statsButtonActive) { fetchDailyData(); } else { fetchAllTimeData(); } setStatsButtonActive(!statsButtonActive); }); return ( <S.Container> <S.Header> <StatsButton onClick={handleClick} isActive={statsButtonActive} /> </S.Header> </S.Container> ) } las funciones de búsqueda están usando useCallback
export const useDashboard = (): Readonly<DashboardOperators> => { const dispatch: any = useDispatch(); const fetchAllTimeData = useCallback(() => { return dispatch(fetchAllTimeDataAction()); }, [dispatch]); const fetchDailyData = useCallback(() => { return dispatch(fetchDailyDataAction()); }, [dispatch]); return { fetchAllTimeData, fetchDailyData, } as const; };No ha publicado todo parent.tsx , pero supongo que handleClick se crea dentro del cuerpo del componente principal. Debido a que la identidad de la función será diferente en cada representación del padre, eso hace que useMemo vea que los accesorios han cambiado, por lo que se volverá a representar.
Dependiendo de si lo que se hace referencia en esa función es estático, es posible que pueda usar useCallback para pasar la misma referencia de función al componente en cada representación.
Tenga en cuenta que hay un RFC para algo incluso mejor que useCallback ; si useCallback no funciona para usted, mire cómo se define useEvent para tener una idea de cómo hacer una mejor referencia de función estática. Parece que incluso se publicó como un nuevo paquete use-event-callback .
Actualizar :
Parece que useCallback no funcionará para usted, presumiblemente porque las variables a las que se hace referencia utilizadas por la devolución de llamada cambian en cada renderizado, lo que hace que useCallback devuelva valores diferentes, lo que hace que la propiedad sea diferente y rompa el caché utilizado por useMemo . Pruebe ese enfoque useEventCallback . Solo para ilustrar cómo funciona todo, aquí hay una implementación ingenua.
function useEventCallback(fn) { const realFn = useRef(fn); useEffect(() => { realFn.current = fn; }, [fn]); return useMemo((...args) => { realFn.current(...args) }, []); } Este useEventCallback siempre devuelve la misma función memorizada, por lo que pasará el mismo valor a sus accesorios y no provocará una nueva representación. Sin embargo, cuando se llama a la función, en su lugar llama a la versión de la función pasada a useEventCallback . Lo usaría así en su componente principal:
const handleClick = useEventCallback(() => { if (!statsButtonActive) { fetchDailyData(); } else { fetchAllTimeData(); } setStatsButtonActive(!statsButtonActive); });