Home > Net >  setState not triggering re-render in React
setState not triggering re-render in React

Time:11-06

Full component:

const Column = ({ form, setForm, fieldset, blocks, selectedFieldsetId, setFieldBeingEdited }) => {
  //Sends block being edited to App component
  const editField = (e) => {
    const blockId = e.currentTarget.getAttribute('data-blockid')
    const data = form.blocks[blockId]
    setFieldBeingEdited({ active: true, data })
  }

  const deleteBlock = (e) => {
    const blockId = e.currentTarget.getAttribute('data-blockid')
    const updatedForm = { ...form }
    delete updatedForm.blocks[blockId]

    for (const fieldset in updatedForm.fieldsets) {
      for (let i = 0; i < updatedForm.fieldsets[fieldset].blockIds.length; i  ) {
        if (updatedForm.fieldsets[fieldset].blockIds[i] === blockId) {
          updatedForm.fieldsets[fieldset].blockIds.splice(i, 1)
          return
        }
      }
    }
    setForm(updatedForm)
  }

  return <BlockList fieldset={fieldset} blocks={blocks} selectedFieldsetId={selectedFieldsetId} editField={editField} deleteBlock={deleteBlock} />
}

I have an object stored in state, but one of my setState calls is not triggering a re render immediately; I have to force some other state change through some other interaction on the page, and only then will the latest state be reflected.

As you can see I'm making a copy of the state object before I make changes to it, and calling setState (setForm) with the new object which has the changes made to it. Is anyone able to tell me where I'm going wrong? Thank you.

In case it's relevant at all, here is the data structure:

const initialData = {
  blocks: {},
  fieldsets: {
    [initialFieldsetId]: {
      id: initialFieldsetId,
      blockIds: [],
    },
  },
  fieldsetOrder: [initialFieldsetId],
}

CodePudding user response:

have you tried creating state separately, as in

const [form, setForm] = useState();

This should work

CodePudding user response:

Not sure how I did it, but now solved (triggers re-render immediately).

New deleteBlock function:

const deleteBlock = (e) => {
    const fieldsetId = e.currentTarget.getAttribute('data-fieldsetid')
    const blockId = e.currentTarget.getAttribute('data-blockid')
    const updatedForm = { ...form }
    const index = updatedForm.fieldsets[fieldsetId].blockIds.findIndex((el) => el === blockId)

    updatedForm.fieldsets[fieldsetId].blockIds.splice(index, 1)
    delete updatedForm.blocks[blockId]
    setForm(updatedForm)
  }

Still not sure exactly what was wrong with previous code, but at least it's working now. I also realise my component structure is a little messy. Just integrating a new library I've never used before so will refactor that after I get it working. Thank you to those who took the time to have a look for me!

  • Related