1

I have an array object inside a state and it will be updated onChange, I was able to update but only for a single property, my problem is if the property has a nested object like the example below, I can't update because I'm not sure on how to pass the field or the property of the selected. Any help will be appreciated.

import React, { useEffect, useState } from 'react';

const TestPage = () => {
  const [state, setState] = useState([
    {
      test: 'test 1',
      current: {
        now: 'now 1',
        prev: 'prev 1'
      }
    },
    {
      test: 'test 2',
      current: {
        now: 'now 2',
        prev: 'prev 2'
      }
    }
  ]);

  const handleChange = ({ prevState, index, params, value }) => {
    const curState = [...prevState];
    curState[index][params] = value;

    setState(curState);
  };

  useEffect(() => {
    console.log(state);
  }, [state]);

  return (
    <div>
      {state.map((item, i) => {
        return (
          <div key={i}>
            <input
              type="text"
              value={item.test}
              onChange={(e) =>
                handleChange({ prevState: state, index: i, params: 'test', value: e.target.value })
              }
            />

            <input
              type="text"
              value={item.current.now}
              onChange={(e) =>
                handleChange({ prevState: state, index: i, params: 'now', value: e.target.value })
              }
            />
          </div>
        );
      })}
    </div>
  );
};

export default TestPage;

Edit:

What if the object has too many nested object like the array object below and I would want to update the others property

const [state, setState] = useState([
    {
      test: 'test 1',
      current: {
        now: 'now 1',
        prev: 'prev 1',
        others: {
            other1: 'other 1',
            other2: 'other 2'
        }
      }
    },
    {
      test: 'test 2',
      current: {
        now: 'now 2',
        prev: 'prev 2'
      }
    }
  ]);
jersrej
  • 62
  • 5

1 Answers1

0
import React, { useEffect, useState } from 'react';

const TestPage = () => {
  const [state, setState] = useState([
    {
      test: 'test 1',
      current: {
        now: 'now 1',
        prev: 'prev 1'
      }
    },
    {
      test: 'test 2',
      current: {
        now: 'now 2',
        prev: 'prev 2'
      }
    }
  ]);

  const handleChange = ({ index, isNested, params, value }) => {
    const curState = [...state];
    if(isNested) {
      curState[index]['current'][params] = value;
    } else {
      curState[index][params] = value;
    }

    setState(curState);
  };

  useEffect(() => {
    console.log(state);
  }, [state]);

  return (
    <div>
      {state.map((item, i) => {
        return (
          <div key={i}>
            <input
              type="text"
              value={item.test}
              onChange={(e) =>
                handleChange({ index: i, params: 'test', value: e.target.value })
              }
            />

            <input
              type="text"
              value={item.current.now}
              onChange={(e) =>
                handleChange({ index: i, isNested: true, params: 'now', value: e.target.value })
              }
            />
          </div>
        );
      })}
    </div>
  );
};

export default TestPage;

You were just trying to update the wrong part of the state, if nested then modify the data under current, not test

David
  • 1,034
  • 11
  • 20
  • Thanks for the answer, @david morton although a follow-up, what if the array has too many nested objects? The answer is only applicable if the object 'current', let's say the state is like this ` const [state, setState] = useState([ { test: 'test 1', current: { now: 'now 1', prev: 'prev 1', others: { other1: 'other 1', other2: 'other 2' } } }, { test: 'test 2', current: { now: 'now 2', prev: 'prev 2' } } ]); ` – jersrej Mar 09 '21 at 12:27
  • @jersrej you would need to search in the state object and only update specific data you want, so you would have to implemented some kind of recursive search to grab for example `current.others.other1`, update it, and then set the state. – David Mar 09 '21 at 12:38
  • 1
    @jersrej maybe something like this https://stackoverflow.com/a/49754647/2600522 – David Mar 09 '21 at 12:44
  • Thanks @David Morton, this comment here actually saved me [link](https://stackoverflow.com/a/46818701/13358236) it's on the same thread though. Again, thanks! – jersrej Mar 09 '21 at 13:11
  • @jersrej no problem, if you could accept my answer I'd appreciate it. Thanks. – David Mar 09 '21 at 13:12