如何在 promise.all 解决时过滤两种不同状态的数据?

How to filter data in two different state when promise.all resolved?

我发送了两个请求来获取

1- 我的服务 2- 管理服务

当我收到响应时,我将状态设置为“myService,admin”。

现在包含我的服务的管理服务。 所以我想过滤我在管理服务中的服务是否从数组中删除管理服务。

所以我正在尝试使用 new Set 但不起作用,也许我错过了什么

另一个问题是我使用 Promise.all 来等待这两个请求,但是当我在那里记录状态时,我得到了初始状态 'empty'

数据样本“我的服​​务和管理员”

[
//my service
  {
    "id": 1,
    "img": ".....",
    "name": "service 1"
  },
  {
    "id": 2,
    "img": ".....",
    "name": "service 2"
  },

  {
    "id": 3,
    "img": ".....",
    "name": "service 3"
  },
//admin service
  {
    "id": 1,
    "img": ".....",
    "name": "service 1"
  },
]

代码片段

  const [myServices, setMyServices] = useState([]);
  const [adminServices, setAdminServices] = useState([]);
  const [allService, setAllService] = useState([]);

  useEffect(() => {
    const getAdminServices = async () => {
      let AuthStr = `Bearer ${token}`;
      const headers = {
        Authorization: AuthStr,
        Accept: 'application/json',
      };
      Api.post('/admin/service', {}, {headers})
        .then((res) => {
          let {services} = res.data;
          let serviceModified = [];
          services.map((service) => {
            serviceModified.push({
              id: service.id,
              name: service.service_name,
              img: DOMAIN_URL + service.images_show[0]?.image,
            });
          });
          console.log('admin', serviceModified);
          setAdminServices(serviceModified);
        })
        .catch((err) => console.log('err', err));
    };

    const getMyServices = async () => {
      let AuthStr = `Bearer ${token}`;
      const headers = {
        Authorization: AuthStr,
        Accept: 'application/json',
      };
      Api.post('/vendor/service', {}, {headers})
        .then((res) => {
          let {services} = res.data;
          let serviceModified = [];
          services.map((service) => {
            serviceModified.push({
              id: service.id,
              name: service.service_name,
              img: DOMAIN_URL + service.images_show[0]?.image,
            });
          });
          console.log('mine', serviceModified);
          setMyServices(serviceModified);
          setSelectedService(serviceModified); // for checkbox
        })
        .catch((err) => console.log('err', err));
    };

    Promise.all([getMyServices(), getAdminServices()]).then(() => {

      let allServices = [...myServices, ...adminServices]; // log empty!
      let uniq = [...new Set(allServices)];
      console.log(myServices);
      console.log('filtered', uniq);
      console.log('here i want to filter the data', allServices);
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);


UI

<FlatList
       data={allService}
       keyExtractor={(item, index) => String(index)}
       renderItem={renderMyServices}
   />

我认为您使用 promises.all 有误。

理想情况下 promises.all 仅当您承诺的所有功能 return 都可以等待时才能等待,但在您的情况下,您正在 returning undefined.

因此甚至在 API 调用响应之前 Promises.all 将完成执行并且 then 也会执行。

您可以将代码重组为如下所示, (不过,我看到了很大的重构空间)。


  const [myServices, setMyServices] = useState([]);
  const [adminServices, setAdminServices] = useState([]);
  const [allService, setAllService] = useState([]);

  useEffect(() => {
    const getAdminServices = async () => {
      let AuthStr = `Bearer ${token}`;
      const headers = {
        Authorization: AuthStr,
        Accept: 'application/json',
      };
      return Api.post('/admin/service', {}, {headers});
    };

    const setMyServices = (res) => {
       let {services} = res.data;
       let serviceModified = [];
       services.map((service) => {
       serviceModified.push({
           id: service.id,
           name: service.service_name,
           img: DOMAIN_URL + service.images_show[0]?.image,
          });
       });
       console.log('mine', serviceModified);
       setMyServices(serviceModified);
       setSelectedService(serviceModified); // for checkbox
       return serviceModified;
    }
    
    const setAdminServices = (res) => {
       let {services} = res.data;
       let serviceModified = [];
       services.map((service) => {
            serviceModified.push({
              id: service.id,
              name: service.service_name,
              img: DOMAIN_URL + service.images_show[0]?.image,
            });
          });
          console.log('admin', serviceModified);
          setAdminServices(serviceModified);
       return serviceModified;
     }  


    const getMyServices = async () => {
      let AuthStr = `Bearer ${token}`;
      const headers = {
        Authorization: AuthStr,
        Accept: 'application/json',
      };
      return Api.post('/vendor/service', {}, {headers});
    };

    Promise.all([getMyServices(), getAdminServices()]).then((data) => {
      console.log(data); // will have [myServiceResponse, adminServiceReponse];
      const myServices = setMyServices(data[0]);
      const adminServices = setAdminServices(data[1]);
      let allServices = [...myServices, ...adminServices]; // log empty!
      // set doesn't work this way, use `uniq` utility function from `lodash` or develop a custom one if required.
      let uniq = [...new Set(allServices)];
      console.log(myServices);
      console.log('filtered', uniq);
      console.log('here i want to filter the data', allServices);
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

首先你应该return getMyServicesgetAdminServices 的承诺。

此外,在 React 中设置状态是异步的。因此 myServicesadminServices 的更新不能保证在您尝试使用它们时反映出来。我建议你 return 承诺的结果并使用这些值而不是状态。

示例:

  const [myServices, setMyServices] = useState([]);
  const [adminServices, setAdminServices] = useState([]);
  const [allService, setAllService] = useState([]);

  useEffect(() => {
    const getAdminServices = () => {
      let AuthStr = `Bearer ${token}`;
      const headers = {
        Authorization: AuthStr,
        Accept: 'application/json',
      };
      return Api.post('/admin/service', {}, {headers})
        .then((res) => {
          let {services} = res.data;
          let serviceModified = [];
          services.map((service) => {
            serviceModified.push({
              id: service.id,
              name: service.service_name,
              img: DOMAIN_URL + service.images_show[0]?.image,
            });
          });
          console.log('admin', serviceModified);
          return serviceModified;
        })
        .catch((err) => console.log('err', err));
    };

    const getMyServices = () => {
      let AuthStr = `Bearer ${token}`;
      const headers = {
        Authorization: AuthStr,
        Accept: 'application/json',
      };
      return Api.post('/vendor/service', {}, {headers})
        .then((res) => {
          let {services} = res.data;
          let serviceModified = [];
          services.map((service) => {
            serviceModified.push({
              id: service.id,
              name: service.service_name,
              img: DOMAIN_URL + service.images_show[0]?.image,
            });
          });
          console.log('mine', serviceModified);
          return serviceModified;
        })
        .catch((err) => console.log('err', err));
    };

    Promise.all([getMyServices(), getAdminServices()]).then(([myServices, adminServices]) => {
      // set state and do stuff
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);