Tengo un creador de documentos simple que permite a los usuarios crear múltiples campos de dos tipos (campo de entrada y campo de etiqueta). También pueden reorganizar el campo arrastrando y soltando. Mi estructura de datos se basa en la guía Redux sobre normalización de datos.
El campo LISTA es de tipo de entrada (por ejemplo, ID de niños 21 y 22): onChange enviará la acción y permitirá que el texto de entrada se modifique sin volver a representar otros campos.
Con el campo ETIQUETA, permitimos a los usuarios seleccionar de una lista desplegable de solo 3 etiquetas (Peligro, Resbaladizo, Inflamable). Seleccionando uno con eliminarlo de la lista desplegable para evitar etiquetas duplicadas. Por ejemplo, si hay "Peligro" y "Resbaladizo" en el campo, el campo desplegable solo mostrará una opción "Inflamable". Para lograr esto, uso createSelector para obtener todos los elementos secundarios y filtrarlos según su elemento principal (fieldId). Esto me da una serie de etiquetas existentes ["Peligro", "Resbaladizo"] en ese ID de campo. Esta matriz se usará para filtrar desde una matriz desplegable fija de tres opciones con useEffect.
Ahora, cada vez que actualice el texto de entrada, también se volverá a representar el campo ETIQUETA (basado en el perfilador de Chrome React).
No afecta el rendimiento, pero siento que me falta algo con mi createSelector .
Example: export const documentSlice = createSlice({ name: "document", initialState: { fields: { 1: { id: 1, children: [11, 12] }, 2: { id: 2, children: [21, 22] }, }, children: { 11: { id: 11, type: "LABEL", text: "Danger", fieldId: 1 }, 12: { id: 11, type: "LABEL", text: "Slippery", fieldId: 1 }, 21: { id: 21, type: "LIST", text: "", fieldId: 2 }, 22: { id: 22, type: "LIST", text: "", fieldId: 2 }, }, fieldOrder:[1,2] }, });crearSelector
export const selectAllChildren = (state) => state.document.children; export const selectFieldId = (state, fieldId) => fieldId; export const getChildrenByFieldId = createSelector( [selectAllChildren, selectFieldId], (children, fieldId) => { const filterObject = (obj, filter, filterValue) => Object.keys(obj).reduce( (acc, val) => obj[val][filter] !== filterValue ? acc : [...acc, obj[val].text], [] ); const existingChildren = filterObject(children, "fieldId", filterId); return existingChildren; } );Después de leer más, esto es lo que finalmente funciona para mí. Con suerte, alguien lo encontrará útil.
slice.js export const getChildrenByFieldId = createSelector( [selectAllChildren, selectFieldId], (children, fieldId) => { // get the children from fields entry => array [11,12] const childrenIds = state.document.fields[fieldId].children let existingChildrenText = []; // loop through the created array [11,12] childrenIds.forEach((childId) => { // pull data from the individual children entry const childText = children[childId].text; existingChildrenText.push(childText); }); return existingChildrenText; } ); //app.js import { shallowEqual, useSelector } from "react-redux"; const childrenTextData = useSelector((state) => { return getChildrenByFieldId(state, blockId); }, shallowEqual);