Home > Enterprise >  setState does not change/rerender
setState does not change/rerender

Time:11-30

I work on a frontend-prototype of an app with a given tech stack of JS, React and CoreUI4 React. I come from a Python background and don't have that much experience in web development and my given tech stack. This became evident when I had to start to work with hooks.

Problem

I don't really understand why it is not updating my usestate and/or doesn't render. I need a conditional render where I also use setState.

I tried to:

  • pass one bigger state from my main app, didn't work once I started conditional logic (Rule of Hooks)
  • implement useEffect as seen here and in other variations, didn't change anything.
  • and a lot of other stuff that I don't recall and didn't work.

When I click one of the Buttons the console gives me this info:

test1.js:21 useEffect //3 times from first render
test1.js:33 clicked (3) ['Some other Stuff available', '', 'cbutton']
test1.js:34 _testSubL  (3) ['Some other Stuff available', '', 'cbutton']
test1.js:46 tmpState:  (3) ['Some other Stuff available', 'pass', 'cbutton']
test1.js:47 btUS:  (3) ['Some other Stuff available', '', 'cbutton']
test1.js:21 useEffect

and on the second and following clicks:

test1.js:33 clicked (3) ['Some other Stuff available', 'pass', 'cbutton']
test1.js:34 _testSubL  (3) ['Some other Stuff available', '', 'cbutton']
test1.js:46 tmpState:  (3) ['Some other Stuff available', 'pass', 'cbutton']
test1.js:47 btUS:  (3) ['Some other Stuff available', 'pass', 'cbutton']
test1.js:21 useEffect

I create a smaller test version where everything is in one file and doesn't import data or any other custom functions.

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

import { CButton, CCol, CRow, CContainer } from '@coreui/react'

var tmpState = []
var inp1 = {
  id: 2,
  TestPhase: 'TestPhase',
  results: [
    [['File Input', 'some Doc', 'file']],
    [['Some Stuff available', 'pass', 'cbutton']],
    [['Some other Stuff available', '', 'cbutton']],
  ],
}.results
const ChangeButton = (_testSubL) => {
  const [btUS, setbtUS] = useState(_testSubL)

  useEffect(() => {
    console.log('useEffect')
  }, [btUS])

  //console.log('begin from: ', _testSubL)
  return (
    <>
      <CButton
        className="mx-1"
        color="secondary"
        shape="rounded"
        size="sm"
        onClick={() => {
          console.log('clicked', btUS)
          console.log('_testSubL ', _testSubL)
          tmpState = btUS
          if (_testSubL[2] == 'cbutton' && _testSubL[1] == 'pass') {
            tmpState = [_testSubL[0], 'fail', _testSubL[2]]
          } else if (_testSubL[2] == 'cbutton' && _testSubL[1] == 'fail') {
            tmpState = [_testSubL[0], 'pass', _testSubL[2]]
          } else if (_testSubL[2] == 'cbutton' && _testSubL[1] == '') {
            tmpState = [_testSubL[0], 'pass', _testSubL[2]]
          } else {
            //pass
          }
          setbtUS(tmpState)
          console.log('tmpState: ', tmpState)
          console.log('btUS: ', btUS)
        }}
      >
        Change
      </CButton>
    </>
  )
}
const TestMain = () => {
  return (
    <>
      <CContainer>
        <h3>Just some Test Page</h3>
        {inp1.map((_subl) => (
          <CRow className="justify-content-center pt-1" key={_subl[0][0]}>
            <CCol md="2">Some Icon: {_subl[0][1]}</CCol>
            <CCol md="3">{_subl[0][0]}</CCol>
            <CCol md="3">{ChangeButton(_subl[0])}</CCol>
          </CRow>
        ))}
      </CContainer>
    </>
  )
}

export default TestMain

Thanks for reading, I hope this is understandable, since it is my first post

CodePudding user response:

You don't see immediately the new state because setState works in an asynchronous way, so it doesn't update itself immediately. For this reason the first time you don't see it updated immediately on the first time.

CodePudding user response:

If you need to see the console.log of updated state, you can make your callback asynchronous and await console.log.

async () => {
  ...
  setbtUS(tmpState);
  await console.log('tmpState: ', tmpState);
  await console.log('btUS: ', btUS);
}

CodePudding user response:

You can get an updated value here in useeffect hook of that particular state variable as it doesn't update itself immediately. And put your logic here after getting new value.

  useEffect(() => {
    console.log('useEffect btUS', btUS)
  }, [btUS])
  • Related