Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

react state resets after calling setvariable again within a function

Okay, so I have a function that has a dropdown with category options. Once a category is selected, it will fill in a multi select (react-select) with its corresponding subcategories. The problem I have is when the category is selected, it adds it to my values object using setValues. That works. But during the callback function of the getSubcategories, I want to set the subcategoriesList portion to all the subcategories that get returned. When I do that, it ignores the category. I use JSON.stringify to display it to the web page and I can see the value show up, then disappear. It only happens during my the callback function and setting the subcategorieslist variable.

// My initial state
const initialState = {
  category: '',
  subcategoriesList: [],
}

// Set initial state
const [values, setValues] = useState(initialState)

// CategoryChange Handler
const handleCategoryChange = (e) => {
  setValues({...values, category: e.target.value})
  // It's working so far, category is displayed correctly
  getSubcategories(e.target.value).then((res) => {
    let options = []
    res.data.map((option) => {
      options.push({value: option._id, label: option.name})
    })
    // This line below is what gets rid of my category
    // Also sets the subcategoriesList correctly
    setValues({...values, subcategoriesList: options})
  })}

I’m using JSON.stringify(values.category) and it will display the value of category for a split second, then disappear. When trying to enter it into my database I get the error of Cast to ObjectId failed for value "" (type string) at path "category" because of "BSONError"

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The values state used here setValues({...values, subcategoriesList: options}) is the original value before you’ve added the category. The new value is added on the next render, and a new values const is created, but the function (closure) that handles the response contains a reference to the old one.

Due to the async nature of React’s state updates (the state is updated on the next render), when you have multiple state changes, and each of them should use the previous updated state, use an updater function:

If you pass a function as nextState, it will be treated as an updater
function. It must be pure, should take the pending state as its only
argument, and should return the next state. React will put your
updater function in a queue and re-render your component. During the
next render, React will calculate the next state by applying all of
the queued updaters to the previous state.

Code:

const handleCategoryChange = (e) => {
  setValues(v => ({ ...v, category: e.target.value }))

  getSubcategories(e.target.value).then((res) => {

    const subcategoriesList = res.data.map(option => (
      {value: option._id, label: option.name}
    ))
    
    setValues(v => ({ ...v, subcategoriesList }))
  })}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading