【问题标题】:UseEffect hook not work well when re update data?重新更新数据时 UseEffect 挂钩无法正常工作?
【发布时间】:2020-09-05 07:00:38
【问题描述】:

我有一个订单列表,我正在使用 FlatList 来呈现它们, 我有 2 个主要概念我应该有“加载更多,拉到刷新”

在我的情况下,用户可以编辑订单然后拉动刷新以获取新更新的数据,另一种情况是加载更多“分页”。

所以 加载更多功能正常工作,并从服务器获取新数据并推送到带有旧数据的状态,

BUT pull to refresh不起作用,setState时并没有更新数据,虽然触发了获取数据的函数,我可以在控制台看到更新的数据,它只是渲染旧数据!

这是一个代码 sn-p。

const OpenedAppointments = () => {
  const [openedAppointment, setOpenedAppointment] = useState([]);
  const [currentPage, setCurrentPage] = useState(1);
  const [lastPage, setLastPage] = useState(null);
  const [loading, setLoading] = useState(false);
  const [isFetch, setIsFetch] = useState(false);


 const loadMoreOrders = () => {
    if (currentPage <= lastPage - 1) {
      setLoading(true);
      setCurrentPage((prevPage) => prevPage + 1);
      console.log('loadMore??');
    }
  };


  const getOpenOrders = useCallback(() => {
    let AuthStr =
      'Bearer ';

    const headers = {
      'Content-Type': 'application/json',
      Authorization: AuthStr,
    };
    Api.post(
      `/open_orders?page=${currentPage}`,
      {},
      {
        headers,
      },
    )
      .then((res) => {
        let last_Page = res.data.open_orders.last_page;
        let allOpenedOrders = res.data.open_orders.data;
        console.log('allOpenedOrders', allOpenedOrders);
        console.log('last_Page', last_Page);
        console.log('currentPage', currentPage);
        setLastPage(last_Page);
        setOpenedAppointment((prevOpenedOrders) => [
          ...prevOpenedOrders,
          ...allOpenedOrders,
        ]);
        setLoading(false);
        setIsFetch(false);
      })
      .catch((err) => console.log('err', err));
  }, [currentPage]);
    
 // Delete Appointments
  const cancelAppointem = (appointmentID) => {
    let AuthStr =
      'Bearer...';

    const headers = {
      'Content-Type': 'application/json',
      Authorization: AuthStr,
    };
    Api.post(
      '/cancel/order',
      {
        id: appointmentID,
      },
      {
        headers,
      },
    )
      .then((res) => {
        setIsOpenedCancelModal((opened) => !opened);
        console.log(res.data);
        setOpenedAppointment((prev) =>
      prev.filter((item) => item.id !== appointmentID),
    ); // works very well
      })
      .catch((err) => console.log(err));
  };

  const _refresh = () => {
    setIsFetch(true);
    getOpenOrders();
  };

  useEffect(() => {
    getOpenOrders();
  }, [getOpenOrders]);

  const keyExtractor = (item, index) => String(index);



  return (
    <FlatList
      showsVerticalScrollIndicator={false}
      contentContainerStyle={styles.flatListCon}
      data={openedAppointment}
      ListEmptyComponent={renderEmpty}
      renderItem={renderItems}
      keyExtractor={keyExtractor}
      ListFooterComponent={_renderFooter}
      onEndReached={loadMoreOrders}
      onEndReachedThreshold={0.1}
      onRefresh={_refresh}
      refreshing={isFetch}
    />
  );
};

找出问题

在第一次渲染时,我从 API 获得了 5 个订单,如果我更新第一个订单然后拉动刷新,我再次获得相同的 5 个订单,但第一个订单已更新 所以在getOpenOrders 函数中,它将旧订单与新订单合并,所以我可以看到重复的订单前 5 个订单“旧数据” 第二个 5 顺序“更新数据”。

但是我有其他概念可以加载更多“分页”,所以我应该让合并的数组在下一页“2”中获得新订单,而前一页中的上一个订单是“1”!

那么我该如何解决这个问题?

编辑数据结构响应

open_orders = [
   {id: 14, status: "Cash", cost: "25.00", service_id: 11, vendor_id: 3, …}
   {id: 15, status: "Cash", cost: "25.00", service_id: 11, vendor_id: 3, …}
    ...
]

【问题讨论】:

    标签: javascript reactjs react-native fetch


    【解决方案1】:

    你的效果应该听 isFetch

      const _refresh = () => {
        setIsFetch(true);
      };
    
      useEffect(() => {
        getOpenOrders();
      }, [isFetch]);
    
    

    【讨论】:

    • 嘿,它没有按预期工作! useEffect 中的另一件事我从 linter React Hook useEffect has a missing dependency: 'getOpenOrders'. Either include it or remove the dependency array. 收到了这个警告另外,我可以得到重复的数据,如您在 Figure out the problem 部分中看到的那样
    【解决方案2】:
    const [updatePage, setUpdatePage] = useState(1)
    const [isUpdate, setIsUpdate] = useState(false)
    
    // call `setUpdatePage` when you edit the data
    /**
    *  const edit = (record)=>{
    *     ...
    *     const updatePageIndex = openedAppointment.findIndex((item)=> item.id === record.id)
    *     const updatePageNum = Math.ceil(updatePageIndex/openedAppointment.length)
    *     setUpdatePage(updatePageNum)
    *     setIsUpdate(true)
    *  }
    *  
    **/
    const getOpenOrders = useCallback(() => {
        const pageNum = isUpdate ? updatePage : currentPage
        let AuthStr =
          'Bearer ';
    
        const headers = {
          'Content-Type': 'application/json',
          Authorization: AuthStr,
        };
        Api.post(
          `/open_orders?page=${pageNum}`,
          {},
          {
            headers,
          },
        )
          .then((res) => {
            let last_Page = res.data.open_orders.last_page;
            let allOpenedOrders = res.data.open_orders.data;
            ...
            if(openedAppointment.length > 0) {
              const newOpenedOrders = openedAppointment.map((item)=>{
                 const target = allOpenedOrders.find(ele=> ele.id === item.id) || []
                 return {
                  ...item,
                  ...target,
                 }
              })
              setOpenedAppointment(newOpenedOrders);
            } else {
              setOpenedAppointment(allOpenedOrders)
            }
            setIsUpdate(false)
            ...
          })
          .catch((err) => console.log('err', err));
      }, [currentPage]);
    

    【讨论】:

    • 嘿!一开始渲染 openedAppointment 它是空的,那么在这种情况下我们如何使用 .map() 呢?
    • 其实我猜当你更新data时,得到的数据不是你编辑的那个
    • 我知道这里有什么问题。比如currentPage是2,但是你改变了第一页的data所以当你从服务器获取数据时,你不能得到新的第一页的数据
    • 当我想在当前页面 1 的前 5 个订单中编辑第一个订单时,首先渲染数据会更新,当我向下滚动时,它应该从下一页“2”获取订单替换了前 5 个订单,除了第一个订单仍然存在 我想当我重新更新第一个订单并再次拉动刷新时,我看不到新的更新“我知道也许你觉得它很复杂”请检查 this截图可能会有所帮助!
    猜你喜欢
    • 2019-08-19
    • 2021-06-16
    • 1970-01-01
    • 2019-09-23
    • 1970-01-01
    • 2019-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多