Tengo js arr obj como se muestra a continuación. Mi necesidad es sumar valor a useState en base a la categoría en el arr obj.
const [fit, setFit] = useState(0) const [fat, setFat] = useState(0) const [slim, setSlim] = useState(0) const [test, setTest] = useState(0) const arr = [ {id: '222', cost: 2, category: 'fit'}, {id: '333', cost: 3, category: 'fat'}, {id: '11', cost: 1, category: 'fat'}, {id: '11', cost: 0, category: 'fit'}, {id: '33', cost: 55, category: 'slim'}, {id: '55', cost: 33, category: 'slim'}, {id: '123', cost: 4, category: 'slim'} ]¿Cómo puedo interactuar para obtener este efecto?
const [fit, setFit] = useState(2) const [fat, setFat] = useState(4) const [slim, setSlim] = useState(92) const [test, setTest] = useState(0)Gracias por tu ayuda ;-)
Puede usar una combinación de filter para filtrar solo la categoría adecuada y luego reduce a valores de suma
const [fit, setFit] = useState( arr.filter(f => f.category === "fit").reduce((acc, c) => acc + c.cost, 0) )Sin embargo, deberá hacerlo para cada estado, lo que podría ser un poco redondo, por lo que creo que es mejor tener solo un estado, con una "matriz de categorías" a través de la cual puede mapear para crear su estado con X categorías. Algo como eso
const [state, setState] = useState( ['fit', 'fat', 'slim', 'test'].reduce((cats, currentCat) => ({ ...cats, [currentCat]: arr.filter(f => f.category === currentCat).reduce((acc, c) => acc + c.cost, 0) }), {}) ) Entonces, si necesita agregar categorías, solo tiene que agregarlas en su matriz, y puede acceder a cada costo usando state.fit , state.fat ,...
No me gustaron las otras respuestas. Este es diferente en el sentido de que creará un objeto basado en todas las propiedades en su matriz, usa useEffect dinámicamente y solo itera a través de su matriz una vez.
const arr = [ {id: '222', cost: 2, category: 'fit'}, {id: '333', cost: 3, category: 'fat'}, {id: '11', cost: 1, category: 'fat'}, {id: '11', cost: 0, category: 'fit'}, {id: '33', cost: 55, category: 'slim'}, {id: '55', cost: 33, category: 'slim'}, {id: '123', cost: 4, category: 'slim'} ]; // reduce list to an object of total costs const values = arr.reduce((a, b) => { if (!a[b.category]) a[b.category] = b.cost; else a[b.category] += b.cost; return a; }, {}); console.log(values); // create your values and setters in an object const effects = {}; for (let key in values) { let [val, set] = useEffect(values[key]); // useEffect is not defined on StackOverflow effects[key] = {val, set}; } /* Creates obj with this structure: { "fit": { "val": fit, "set": setFit, }, ... } */Puede crear la función con reducir. Como esto:
const arr = [ { id: "222", cost: 2, category: "fit" }, { id: "333", cost: 3, category: "fat" }, { id: "11", cost: 1, category: "fat" }, { id: "11", cost: 0, category: "fit" }, { id: "33", cost: 55, category: "slim" }, { id: "55", cost: 33, category: "slim" }, { id: "123", cost: 4, category: "slim" } ]; const sumArrBy = (arr = [], category = "") => arr.reduce( (prev, { cost, category: cat }) => cat === category ? prev + cost : prev, 0 ); console.log(sumArrBy(arr, 'fit')) console.log(sumArrBy(arr, 'fat')) console.log(sumArrBy(arr, 'slim'))Entonces puedes configurar tu estado así:
const [fit] = useState(sumArrBy(arr, "fit")); const [fat] = useState(sumArrBy(arr, "fat")); const [slim] = useState(sumArrBy(arr, "slim"));Código completo:
export default function App() { const arr = [ { id: "222", cost: 2, category: "fit" }, { id: "333", cost: 3, category: "fat" }, { id: "11", cost: 1, category: "fat" }, { id: "11", cost: 0, category: "fit" }, { id: "33", cost: 55, category: "slim" }, { id: "55", cost: 33, category: "slim" }, { id: "123", cost: 4, category: "slim" } ]; const sumArrBy = (arr = [], category = "") => arr.reduce( (prev, { cost, category: cat }) => cat === category ? prev + cost : prev, 0 ); const [fit] = useState(sumArrBy(arr, "fit")); const [fat] = useState(sumArrBy(arr, "fat")); const [slim] = useState(sumArrBy(arr, "slim")); return ( <div className="App"> <h1>Hello CodeSandbox</h1> <h2>Start editing to see some magic happen!</h2> <div> {fit}, {fat}, {slim}{" "} </div> </div> ); }La demostración de trabajo que puede encontrar aquí - codesandbox
EDITAR: Otras soluciones para este problema tienen la función de "filtro", que no es necesariamente, porque hace otro ciclo para filtrar valores. En mi caso, no uso el "filtro". Mi solución es verificar la categoría directamente en "reducir". Comprueba la categoría, y si la categoría es verdadera, la función agrega valor costo a los resultados, si no, salta y devuelve el valor anterior correctamente.