Estoy haciendo algunas pruebas en mi interfaz de usuario y me di cuenta de que si algún estado cambia en mi tienda redux, mi componente (que se muestra a continuación) se vuelve a procesar y se reinicia con el video incrustado en 0. Si escribo en un campo de texto conectado a redux , se vuelve a montar, si una notificación de estado llega a la tienda, se vuelve a montar, etc.
No tengo idea de cómo solucionar esto y realmente me vendría bien un poco de ayuda para averiguar cómo solucionar el error.
tldr; ¿Cómo puedo evitar que mi VideoPlayer se reproduzca cada vez que algo cambia en mi tienda redux?
redux-toolkitreact const MyComponent = () => { ... // data used in the VideoPlayer is descructured from this variable: const formState = useSelector(selectDynamicForm); // renders output here in the same component return ( ... {sourceContentFound === false ? ( <VideoPlayerDisabled /> ) : ( <VideoPlayerController title={title} description={description} sourceAddress={iframeURL} author={authorName} timeStamp={{ startTime: 0 }} /> )} ) ... } export const dynamicFormSlice = createSlice({ name: 'dynamicForm', initialState, reducers: { updateField: (state, action) => { state = action.payload; return state; } }, }); export const selectDynamicForm = createSelector( (state: RootState): dynamicFormState => state.dynamicForm, dynamicForm => dynamicForm ); No creo que este componente haga nada loco, por ejemplo, pero aparece una notificación cuando se cumplen las condiciones del video. Cuando vuelve a bajar clearStatus , el reproductor de video se reinicia.
export const statusHandlerSlice = createSlice({ name: 'statusHandler', initialState, reducers: { setStatus: (state, action: PayloadAction<IStatusObject>) => { const { type, display, message } = action.payload; state.status = { ...action.payload, message: message.charAt(0).toUpperCase() + message.slice(1), }; if (display === 'internal-only' || display === 'support-both') { statusLogger(type, message); } }, clearStatus: state => { state.status = { type: 'success', data: {}, message: '', display: 'internal-only', key: '', }; }, }, }); export const { setStatus, clearStatus } = statusHandlerSlice.actions; export const selectStatus = (state: RootState): IStatusObject => state.statusHandler.status;Su MyComponent se vuelve a renderizar cada vez que el cambio de estado de la tienda redux se debe a que tiene un selector en él
Puede evitar que esto suceda agregando un equalFn a useSelector .
Puede escribir su propia equalityFn o usar alguna función existente de una biblioteca que admita una comparación profunda.
Ej: Usar lodash isEqual
import { isEqual } from 'lodash'; const MyComponent = () => { ... // data used in the VideoPlayer is descructured from this variable: const formState = useSelector(selectDynamicForm, isEqual); De forma predeterminada, useSelector usa una comparación shallow que no puede detectar cambios profundos dentro de su objeto, cambiar a una función de comparación profunda como isEqual lo ayudará a hacerlo, pero no se recomienda para todos los selectores ya que habrá un impacto en el rendimiento.
Ejemplo en vivo:
const { data } = useSelector(store => store.sliceA, shallowEq); // console.log(data) => { a: "foo", b: "bar" } // data.b is useless but once it is changed, the component will re-render as well return <Typography>{data.a}</Typography> Debe instalar React Devtools, activar el generador de perfiles, recordar verificar Record why each component rendered while profiling en la configuración para ver qué está causando que se vuelva a procesar. a veces, los ganchos personalizados en las bibliotecas desencadenan una nueva representación.
whyDidYouRender también es una buena opción