Tengo un componente MenuOptions al que le paso un accesorio de opciones. Opciones es una gran variedad de objetos. Cada objeto tiene una matriz anidada llamada 'servicios' dentro de los servicios es un objeto con una clave 'tipo de servicio' que es el único valor que quiero. Quiero tomar todos esos valores, insertarlos en una nueva matriz y eliminar cualquier duplicado si hay alguno, y luego mapear a través de esa nueva matriz y mostrar cada elemento en una etiqueta html de 'opción'.
aquí está mi función createArray:
const createNewArray = () => { let optionsArr = [] let uniqueArr; options.map((option) => { option.services.map((service) => optionsArr.push(service.serviceType)) }) uniqueArr = [...new Set(optionsArr)]; return uniqueArr; }
uniqArr parece tener lo que quiero, pero ahora quiero configurar esto en un estado global. Intentar algo así no funciona. la matriz parece estar configurada como nula
const [array, setArray] = useState(null) useEffect(() => { setArray(createNewArray()) }, [])
¿alguna solución? Gracias
1) Debe agregar el valor inicial del estado de su array
como una matriz vacía:
const [array, setArray] = useState([]);
Demo en vivo
2) Puede simplificar la creación de una nueva matriz como:
const createNewArray = () => [ ...new Set(options.flatMap((o) => o.services.map((obj) => obj.serviceType))) ];
3) establecer el estado de la array
en useEffect
como:
useEffect(() => { setArray(createNewArray()); }, []);
Según su descripción, ¿estos son sus datos?
const options = [{ services: [ { serviceType: 'serviceType', } ], },{ services: [ { serviceType: 'serviceType', } ], },{ services: [ { serviceType: 'serviceType', } ], }, { services: [ { serviceType: 'serviceType', } ], }]
aquí está la solución
const uniq = (a) => [...new Set(a)]; const createNewArray = (array) => { const c = [...array] const newArray = [] for (let i = 0; i < c.length; i++) { const e = c[i]; for (let ii = 0; ii < e.length; ii++) { const ee = e[ii].serviceType; newArray.push(ee); } } const toReturn = uniq(newArray) return toReturn; }
Si desea opciones únicas, simplemente pase las opciones y configúrelas en el estado después de manipular los datos.
const { useEffect, useMemo, useState } = React; const unique = (arr) => [...new Set(arr)]; const uniqueOptions = (options) => unique(options.flatMap(({ services }) => services.map(({ serviceType }) => serviceType))); const data = { options: [ { services: [{ serviceType: "Home" } , { serviceType: "About" }] }, { services: [{ serviceType: "About" } , { serviceType: "Help" }] }, { services: [{ serviceType: "Help" } , { serviceType: "Home" }] }, ], }; const MenuOptions = (props) => { const { options } = props; const [opts, setOpts] = useState([]); useEffect(() => setOpts(uniqueOptions(options)), [options]); return useMemo( () => ( <select> {opts.map((opt) => ( <option key={opt} value={opt}> {opt} </option> ))} </select> ), [opts] ); }; const App = ({ title }) => useMemo( () => ( <div> <h1>Services</h1> <form> <MenuOptions options={data.options} /> </form> </div> ), [] ); ReactDOM.render(<App />, document.getElementById("react-app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <div id="react-app"></div>