Home > Blockchain >  Fill an object dynamically in react with values from an array
Fill an object dynamically in react with values from an array

Time:12-28

I'm trying to fill an object with values that I'm getting from an array of objects but the object is only getting the value from the last object in the array.

This is a simplified code example

https://codesandbox.io/s/crazy-nobel-c7xdb?file=/src/App.js

import "./styles.css";
import React, { useEffect, useState } from "react";

export default function App() {
  const [fieldsValues, setFieldsValues] = useState({});
  const items = [{ value: "a" }, { value: "b" }, { value: "c" }];

  useEffect(() => {
    items.map((item, index) => {
      return setFieldsValues({
        ...fieldsValues,
        [index]: item.value
      });
    });
  }, []);

  return (
    <div className="App">
      <h2> {` fieldsValues = ${JSON.stringify(fieldsValues)}`} </h2>
    </div>
  );
}

I want the fieldsValues to return this:

{
  0: "a",
  1: "b",
  2: "c"
}

What I'm getting now:

fieldsValues = {"2":"c"}

CodePudding user response:

You fix it by doing this

useEffect(() => {
  items.map((item, index) => {
    return setFieldsValues((prev) => ({
      ...prev,
      [index]: item.value,
    }));
  });
}, []);

Better way of doing this is

useEffect(() => {
  const data = items.reduce(
    (prev, item, index) => ({ ...prev, [index]: item.value }),
    {}
  );

  setFieldsValues((prev) => ({ ...prev, ...data }));
}, []);

CodePudding user response:

To create the object map the array to [index, value] pairs, and convert to an object with Object.fromEntries():

const items = [{ value: "a" }, { value: "b" }, { value: "c" }];

const result = Object.fromEntries(items.map(({ value }, index) => [index, value]))

console.log(result)

However, the way you are using the array, and then need to set the state doesn't actually makes sense in the react context.

If the array is a prop, you should add it to useEffect as a dependency:

const arrToObj = items => Object.fromEntries(items.map(({ value }, index) => [index, value]))

export default function App({ items }) {
  const [fieldsValues, setFieldsValues] = useState({});

  useEffect(() => {
    setState(() => arrToObj(items))
  }, [items]);
  
  ...

If it's a static array, set it as the initial value of setState:

const arrToObj = items => Object.fromEntries(items.map(({ value }, index) => [index, value]))

const items = [{ value: "a" }, { value: "b" }, { value: "c" }];
    
export default function App({ items }) {
  const [fieldsValues, setFieldsValues] = useState(() => arrToObj(items));
      
  ...

CodePudding user response:

By your way It would be like this

  useEffect(() => {
    let test={}
    items.map((item, index) => {
      return setFieldsValues((prev)=>{
        return {
        ...prev,
        [index]: item.value
      }
      });
    });
  }, []);
  • Related