0

I'm trying to fill an object with values that I'm getting from an array of objects but it's not working as expected.

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"}

3 Answers 3

3

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 }));
}, []);
Sign up to request clarification or add additional context in comments.

Comments

1

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));
      
  ...

Comments

0

By your way It would be like this

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.