Home > OS >  useEffect doesn't re-render on state change or infinite looping issue
useEffect doesn't re-render on state change or infinite looping issue

Time:01-03

I have a component which contains a form and a list. When user adds an item to the list though the form, the item should display immediately in the list. I try to use useEffect to fetch data, useEffect without dependency causes an infinite request loop. I added empty array as dependency to prevent looping but in this case new item which is added doesn't display in the list until refreshing the page. How can I solve this issue? (I use antd and antd-form-builder to create the component)

here is my code:

function FieldSetting() {
  const [form] = Form.useForm()
  const [typeValue, setTypeValue] = useState()
  const meta = {
    fields: [{ key: "pathname", onChange: (e) => setTypeValue(e.target.value) }],
  }
  const [data, setData] = useState([])
 async function onFinish() {
    try {
      await axios.post("api", { typeValue, typeId })
      form.resetFields()
    } catch (e) {
      console.log(e)
    }
  }
useEffect(() => {
    const getData = async () => {
      const response = await fetch(`api?id=${typeId}`)
      const newData = await response.json()
      setData(newData)
    }
    getData()
  }, [])
return (
    <Container>
      <Form form={form} layout="inline" className="form-field" onFinish={onFinish}>
        <FormBuilder form={form} meta={meta} />
        <Form.Item>
          <Button type="primary" htmlType="submit">
            Add
          </Button>
        </Form.Item>
      </Form>
      <div
        id="scrollableDiv"
        style={{
          height: 665,
          overflow: "auto",
          padding: "0 16px",
          border: "1px solid rgba(140, 140, 140, 0.35)",
        }}
      >
        <List
          itemLayout="horizontal"
          dataSource={data}
          renderItem={(item) => (
            <List.Item
              actions={[
                <a key="list-edit">edit</a>,
                <a onClick={() => axios.delete(`http://gage.axaneh.com/api/Gages/SettingProduct/RemoveProductSetting/${item.id}`, item)} key="list-delete">
                  delete
                </a>,
              ]}
            >
              <List.Item.Meta title={item.typeValue} />
            </List.Item>
          )}
        />
      </div>
    </Container>
  )
}

export default FieldSetting

CodePudding user response:

Whenever you manipulate your array just add a dummy state and change it

add this state

const [extra, setExtra] = useState(0)

when you change the state of your array like add or remove just add this line below

setExtra(extra 1)

what happens is that adding or removing data in an array don't count as a state change in react as per my understanding it need to be something different like true to false or in this case 0 to 1

CodePudding user response:

Just add a state that will refretch (trigger useEffect) after you have submitted the form. Be aware that it will refetch all the data from the API. This might bring scalability issues when the data grows.

function FieldSetting() {
    const [form] = Form.useForm()
    const [refetch, setRefetch] = useState(false) // <----- add this state
    const [typeValue, setTypeValue] = useState()
    const meta = {
      fields: [{ key: "pathname", onChange: (e) => setTypeValue(e.target.value) }],
    }
    const [data, setData] = useState([])
   async function onFinish() {
      try {
        await axios.post("api", { typeValue, typeId })
        form.resetFields()
        setRefetch(!refetch) // <----- set the refetch to change the state
      } catch (e) {
        console.log(e)
      }
    }
  useEffect(() => {
      const getData = async () => {
        const response = await fetch(`api?id=${typeId}`)
        const newData = await response.json()
        setData(newData)
      }
      getData()
    }, [refetch]) // <----- add the refetch here to trigger the effect
  return (
      <Container>
        <Form form={form} layout="inline" className="form-field" onFinish={onFinish}>
          <FormBuilder form={form} meta={meta} 
          
          
          />
          <Form.Item>
            <Button type="primary" htmlType="submit">
              Add
            </Button>
          </Form.Item>
        </Form>
        <div
          id="scrollableDiv"
          style={{
            height: 665,
            overflow: "auto",
            padding: "0 16px",
            border: "1px solid rgba(140, 140, 140, 0.35)",
          }}
        >
          <List
            itemLayout="horizontal"
            dataSource={data}
            renderItem={(item) => (
              <List.Item
                actions={[
                  <a key="list-edit">edit</a>,
                  <a onClick={() => axios.delete(`http://gage.axaneh.com/api/Gages/SettingProduct/RemoveProductSetting/${item.id}`, item)} key="list-delete">
                    delete
                  </a>,
                ]}
              >
                <List.Item.Meta title={item.typeValue} />
              </List.Item>
            )}
          />
        </div>
      </Container>
    )
  }
  
  export default FieldSetting```
  • Related