Home > Software design >  ReactJs - Create objects with useffect
ReactJs - Create objects with useffect

Time:05-31

i have this problem, code here:

https://codesandbox.io/s/youthful-wozniak-pqp48d?file=/src/App.js

the final object need to have 2 keys, one with Bloco and other with Apto, but only apto shows, i dont know why this happen, can anyone help me? =]

Edit: Problem solved, but i don't know if it is the best answer for that problem, but its working. Thanks for the help!

CodePudding user response:

setUserObjValues(prev=>{return{
      ...prev,
      [name]: { value, complement, type, id, error: value ? false : true }
}});

CodePudding user response:

When you are doing setState inside the mapping, the original value is preserved for the next value in the list. This means that the spread you are doing on line 30 is empty.

You should instead map the list to a final set of values and setState that, instead of for each item in the list.

Psuedo code:

useEffect(() => {
    if (data.complements) {
      const newUserObjValues = data.complements.map((item) => transformItem(item);

setUserObjValues(newUserObjValues)
    }
  }, []);

Where transformItem is a function similar to userCompValues that will return the item instead of trying to setState.

CodePudding user response:

I changed the userCompValues function to only return one object and get the returned value of map function inside useEffect. Try this:

import "./styles.css";
import { useEffect, useState } from "react";
import ReactJson from "react-json-view";

const data = {
  complements: [
    {
      id: "1",
      complement: "abc",
      type: "Bloco",
      value: "10"
    },
    {
      id: "2",
      complement: "dnd",
      type: "Apto",
      value: "25"
    }
  ]
};

export default function App() {
  const [userObjValues, setUserObjValues] = useState({});

  const userCompValues = (target, complement, type, id) => {
    const { value, name } = target;
    return {
      [name]: { value, complement, type, id, error: value ? false : true }
    };
  };

  useEffect(() => {
    if (data.complements) {
      const result = data.complements.map((item) => {
        return userCompValues(
          { value: item.value, name: item.type },
          item.complement,
          item.type,
          item.id
        );
      });

      setUserObjValues(result);
    }
  }, []);

  return (
    <div className="App">
      <div>
        <ReactJson
          style={{ padding: 10, display: "flex", justifyContent: "flex-start" }}
          displayObjectSize
          theme="bright:inverted"
          displayDataTypes={false}
          indentWidth={4}
          src={userObjValues}
        />
      </div>
    </div>
  );
}

CodePudding user response:

A few lines of code and you will get the result that you want.

You can optimise your state change by using this reduce:

export default function App() {
const [userObjValues, setUserObjValues] = useState({});

useEffect(() => {
  let obj = { ...userObjValues };
  if (data.complements) {
    const newState = data.complements.reduce(
      (acc, { value, type, id, complement }) => {
        return {
          ...acc,
          [type]: {
            value,
            type,
            complement,
            id,
            error: value ? false : true
          }
        };
      },
      obj
    );
    setUserObjValues(newState);
  }
}, []);
return (
  <div className="App">
    <div>
      <ReactJson
        style={{ padding: 10, display: "flex", justifyContent: "flex-start" }}
        displayObjectSize
        theme="bright:inverted"
        displayDataTypes={false}
        indentWidth={4}
        src={userObjValues}
      />
    </div>
  </div>
);

}

  • Related