Search code examples
javascriptreactjsjavascript-objectssetstatearray.prototype.map

Setting React state in .map function without overwriting state


New to javascript and I'm struggling with a simple map method.

I'd like to iterate over two arrays of objects, and set state to include the result of each mapping. Currently, state is being overwritten with each new item.

Desired output:

refData = {
 user: [
  {key: 1, value: "A"},
  {key: 2, value: "B"}
 ],
 product: [
  {key: 1, value: "A"},
  {key: 2, value: "B"}
 ],
 role: [
  {key: 1, value: "A"},
  {key: 2, value: "B"}
 ]
}

Current output:

refData = {
 user: [
  {key: 1, value: "A"},
  {key: 2, value: "B"}
 ]
}

refData = {
 product: [
  {key: 1, value: "A"},
  {key: 2, value: "B"}
 ]
}

refData = {
 role: [
  {key: 1, value: "A"},
  {key: 2, value: "B"}
 ]
}

Code that produced the current, incorrect output:

const [refData, setRefData] = React.useState();

  useEffect(() => {

    const refDataArr = [
      { url: "users", field: "user" },
      { url: "products", field: "product" },
      { url: "roles", field: "role" }
    ]

    const fetchRefData = () => {
      try {
        refDataArr.map(async (o, index) => {
          let url = o.url
          let field = o.field
          const res = await axios.get(`http://.../${url}/ `);
          const data = res.data.data

          const resArr = Object.values(data).map((item, index) => {
            return {
              key: item._key,
              value: item[field]
            }
          });
          setRefData({  //overwritten with each returned item
            ...refData, 
            [field]: resArr, 
          })
        })
      } catch (err) {
        console.log(err);
      }
    }
    fetchRefData();
  }, []);

Any help would be really appreciated!


Solution

  • A way to do that is to build the json object first and then set that to the state.

      React.useEffect(() => {
        ..........
        let newRefData = {};
        ..........
        try {
          refDataArr.map(async(o, index) => {
              let url = o.url
              let field = o.field
              const res = await axios.get(`http://.../${url}/ `);
              const data = res.data.data
    
            const resArr = Object.values(data).map((item, index) => {
              return {
                key: item._key,
                value: item[field]
              };
            });
            newRefData[field] = resArr;
          });
          setRefData(newRefData);
        } catch (err) {
          console.log(err);
        }
        ..........
      }, []);