1

I couldn't make the setMajor and setMinor work inside the function.

What happen is, it just overwrite some of the data inside major and keeps on adding data inside minor

I use this code to clear all the value inside the major but it's kinda messy and it looks like I'm not using the useState function properly.

major.forEach((tk) => {
      tk['material'] = ''
      tk['required'] = 0
      tk['actual'] = 0
      tk['difference'] = 0
      tk['crit'] = 0
      tk['percent'] = 0
    })

The handleSelectInput is a select tag that whenever I change the value it would send a request to the server to fetch the correct value for the major and minor variables

const majorStates = [
      {
        tank: 1,
        material: '',
        required: 0,
        actual: 0,
        difference: 0,
        crit: 0,
        percent: 0,
      },
      {
        tank: 2,
        material: '',
        required: 0,
        actual: 0,
        difference: 0,
        crit: 0,
        percent: 0,
      },...10],
[major, setMajor] = useState(tankStates),
[minor, setMinor] = useState([]),

const handleSelectInput= async (e) => {
    const { name, value } = e.target

    setMajor(majorStates) // not working
    setMinor([]) // not working

    await axios
      .put(`${PATH}/main-start`, { product: value })
      .then((res) => {
        for (let i = 0; i < res.data.length; i++) {
          //See if data has a type major or minor
          //ParseFloat for decimal that's been returned as str
          if (res.data[i].type === 'MAJOR') {
            major[i].material = res.data[i].material
            major[i].required = parseFloat(res.data[i].required_wt)
            setMajor([...major])
          } else {
            res.data[i].required_wt = parseFloat(res.data[i].required_wt)
            setMinor([...minor, res.data[i]])
          }
        }
      })
      .catch((err) => {
        console.log(err)
      })
  }

I have a majorStates because it is required that the 10 value is shown even if the fetch data is less than 10.

Sorry if it's a noob question

1
  • When you say "setMajor(majorStates) // not working" and "setMinor([]) // not working" can you be more specific? What specifically isn't working? I doubt that React is broken and not updating state. Commented Jul 8, 2021 at 6:55

1 Answer 1

0

Issue

Based upon enqueueing a bunch of state updates in a loop I'm going to guess that what isn't working is that only the last enqueued state update is what you are seeing. This is caused by starting from the same stale state each loop iteration.

You are also mutating state, major[i].material = res.data[i].material is mutating the major element at index i for example.

Solution

Use functional state updates to update from the previous state, not the state from the previous render cycle. Shallow copy the array and then also shallow copy any nested state/elements that are being updated.

const handleSelectInput= async (e) => {
  const { name, value } = e.target

  setMajor(majorStates) // reset
  setMinor([]) // reset

  await axios
    .put(`${PATH}/main-start`, { product: value })
    .then((res) => {
      for (let i = 0; i < res.data.length; i++) {
        //See if data has a type major or minor
        //ParseFloat for decimal that's been returned as str
        if (res.data[i].type === 'MAJOR') {
          setMajor(major => major.map((el, index) => index === i ? {
            ...el,
            material: res.data[i].material,
            required: parseFloat(res.data[i].required_wt)
          } : el);
        } else {
          res.data[i].required_wt = parseFloat(res.data[i].required_wt)
          setMinor(minor => [...minor, res.data[i]])
        }
      }
    })
    .catch((err) => {
      console.log(err)
    })
}
Sign up to request clarification or add additional context in comments.

1 Comment

That did the trick, I was also wondering how to use a functional update cause it's been popping up in the console as a warning on some of my pages. Thank you :>

Your Answer

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