Problem description

The useEffect array has multiple dependencies and is being updated at the same time. The result will return unstable, not the latest data.

  useEffect(() => {
    setTableListData();
    if (stateDate && endDate) getData(PAGINATION);
  }, [toggleTabData, startDate, endDate, inputId]);
Copy the code

For example, useEffect above relies on switching TAB, start time, end time, and input values, as shown here.

When I tab-switch, I need to reset the time and input to the default value, and then request data to update the latest data of the table. Part of the code is as follows:

import React, { useState, useEffect } from 'react'; import StatusCard from './StatusCard'; import DateRange from './DateRange'; const tradeList = () => { const [toggleTabData, setToggleTabData] = useState(); const [startDate, setStartDate] = useState(); const [endDate, setEndDate] = useState(); const [inputId, setInputId] = useState(); const [tableListData, setTableListData] = useState(); const [dateRange, setDateRange] = useState(); Const columns = [{title: 'name', dataIndex: 'name', key: 'name',}, {title: 'age', dataIndex: 'age', key: 'age', {title: 'address', dataIndex: 'address', key: 'address', }, ] const getData = () => { console.log(toggleTabData, startDate, endDate, inputId) } useEffect(() => { getData() }, [toggleTabData, startDate, endDate, inputId]) useEffect(() => { setStateDate(moment(dateRange.date[0]).valueOf()); setEndDate(moment(dateRange.date[1]).valueOf()); }, [dateRange]); return ( <div> {Object.keys(tabStatusData).length > 0 && ( <StatusCard tabList={tabStatusData} onClickTab={toggleTab} />  )} <InputNumber style={{ width: '200px' }} onChange={handleInputChange} value={inputId} placeholder={formatMessage({ id: 'm-tmall_TradeRecord_Search_Placeholder_Input', defaultMessage: 'input id', })} allowClear /> <DateRange className={styles.inputid} dateRange={setDateRange} defaultDateRange={dateRange} /> <Table rowSelection={rowSelection} columns={columns} dataSource={tableListData} pagination={pagination} loading={loading} onChange={getData} /> </div> )} export default tradeList;Copy the code

When we select a TAB after any time, the desired effect is that the time is reset and the input value is cleared, and then we request the latest data with the reset time and the latest TAB, which is occasionally implemented, or the data is old.

The reason is that useEffect, when updating data by relying on arrays, will send simultaneous update status as long as the data is being updated, and the order of return results cannot be fixed. For example, data is identified to toggleTabData, startDate, When an endDate requests all updates at the same time, it sends three updates concurrently:

1. ToggleTabData, old startDate, old endDate

2. ToggleTabData, new startDate, old endDate

3. ToggleTabData, new startDate, new endDate

These three lines actually run at the same time, so the order of return is not as we need to return the latest data of the third line. So there are two ways to do this

1. Write useEffect for toggleTabData separately and pass in the default values for startDate and endDate. (Not recommended)

  const getData = (front, end) => {
    const newStartDate = front ? front : startDate
    const newEndDate = end ? end : endDate
    console.log(toggleTabData, newStartDate, newEndDate, inputId)
  }  useEffect(() => {
    const  front = moment()
    const  end = moment()
    getData(front, end)
  }, [toggleTabData])
  useEffect(() => {
    getData()
  }, [startDate, endDate, inputId])
Copy the code

Downside: There are two calls to getData on the first request.

2, merge state, toggleTabData, startDate, endDate, inputId need to request at the same time into a state. (Not recommended)

  const [type, setType] = useState({
    toggleTabData: '',
    startDate: '',
    endDate: '',
    inputId: '',
  });
Copy the code

This does not require two requests, but the logic is unreasonable, because each function point is different, the subsequent maintenance difficulty increases sharply.

3. Only obtain the latest data through the principle of data stabilization. (recommended)

In fact, this is similar to the anti-shake function, only to achieve the last content of a logic, borrowed from the Lodash-ES library

Import {useRef, useEffect} from 'react'; import {useRef, useEffect} from 'react'; import { debounce } from 'lodash-es'; const useDebounce = (fn: T, wait = 1000) => { const func = useRef(fn); func.current = fn; const debounceWrapper = useRef(debounce((args) => func.current? .(args), wait)); return debounceWrapper.current as unknown as T; } /** * export function useBatchEffect(effect: any, deps? : any, wait = 0) { const fn = useDebounce(effect, wait); useEffect(fn, deps); } useBatchEffect(() => { getData() }, [toggleTabData, startDate, endDate, inputId])Copy the code

That’s what we need

The article reference from www.jianshu.com/p/ca6765bbd…