Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用React钩子处理/链接依赖于另一个钩子的同步副作用_Javascript_Reactjs_React Hooks - Fatal编程技术网

Javascript 如何使用React钩子处理/链接依赖于另一个钩子的同步副作用

Javascript 如何使用React钩子处理/链接依赖于另一个钩子的同步副作用,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我试图将我的应用程序从redux重写为新的context+钩子,但不幸的是,我很难找到一个好方法来处理一系列同步副作用,这些副作用取决于前一个版本的响应 在我当前的redux应用程序中,我大量使用了同步/链接操作和API请求,我通常通过redux saga或thunks来处理这些请求。因此,当返回第一个API请求的响应时,该数据将用于下一个API请求等 我已经制作了一个定制的钩子“useFetch”(在本例中,它做的不多,因为它是一个简化的版本,我还必须对它进行一些小的调整,以便在codesan

我试图将我的应用程序从redux重写为新的context+钩子,但不幸的是,我很难找到一个好方法来处理一系列同步副作用,这些副作用取决于前一个版本的响应

在我当前的redux应用程序中,我大量使用了同步/链接操作和API请求,我通常通过redux saga或thunks来处理这些请求。因此,当返回第一个API请求的响应时,该数据将用于下一个API请求等

我已经制作了一个定制的钩子“useFetch”(在本例中,它做的不多,因为它是一个简化的版本,我还必须对它进行一些小的调整,以便在codesandbox上工作-请参阅下面的代码)。问题是由于“钩子规则”,我不能在useEffect钩子中使用自定义钩子。那么,如果您有自己的获取数据的钩子,那么如何在执行下一个etc之前等待第一个请求的响应呢?即使我最终放弃了useFetch抽象并创建了一个普通的fetch请求,如何避免最终出现大量useEffects钩子的臃肿混乱呢?这可以做得更优雅一点吗,或者上下文+挂钩在处理副作用方面与redux saga/thunk竞争还为时过早吗

下面的示例代码非常简单。它应该尝试模拟的是:

  • 查询person api端点以获取人员
  • 一旦我们找到了那个人 响应,查询作业端点(在真实世界中使用人员id (场景)
  • 一旦我们有了这个人和工作,根据我们的反应 从人员和作业终结点,查询同事终结点 找一个特定工作的同事
  • 这是密码。为useFetch钩子添加了一个延迟,以模拟真实世界中的延迟:

    import React, { useEffect, useState } from "react";
    import { render } from "react-dom";
    
    import "./styles.css";
    
    const useFetch = (url, delay = 0) => {
      const [data, setData] = useState(null);
    
      useEffect(() => {
        const fetchData = async () => {
          // const result = await fetch(url, {
          //  method: "GET",
          //  headers: { "Content-Type": "application/json" }
          // });
          //const response = await result.json();
          const response = await import(url);
          setTimeout(function() {
            setData(response);
          }, delay);
        };
    
        fetchData();
      }, [url]);
    
      return data;
    };
    
    function App() {
      const [person, setPerson] = useState();
      const [job, setJob] = useState();
      const [collegues, setCollegues] = useState();
    
      // first we fetch the person /api/person based on the jwt most likely
      const personData = useFetch("./person.json", 5000);
      // now that we have the person data, we use the id to query for the
      // persons job /api/person/1/jobs
      const jobData = useFetch("./job.json", 3000);
      // now we can query for a persons collegues at job x /api/person/1/job/1/collegues
      const colleguesData = useFetch("./collegues.json", 1000);
    
      console.log(personData);
      console.log(jobData);
      console.log(colleguesData);
    
      // useEffect(() => {
      //   setPerson(useFetch("./person.json", 5000));
      // }, []);
    
      // useEffect(() => {
      //   setJob(useFetch("./job.json", 3000));
      // }, [person]);
    
      // useEffect(() => {
      //   setCollegues(useFetch("./collegues.json",1000));
      // }, [job]);
    
      return (
        <div className="App">
          <h1>Hello CodeSandbox</h1>
          <h2>Start editing to see some magic happen!</h2>
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    render(<App />, rootElement);
    
    import React,{useffect,useState}来自“React”;
    从“react dom”导入{render};
    导入“/styles.css”;
    const useFetch=(url,延迟=0)=>{
    const[data,setData]=useState(null);
    useffect(()=>{
    const fetchData=async()=>{
    //const result=等待获取(url{
    //方法:“获取”,
    //标题:{“内容类型”:“应用程序/json”}
    // });
    //const response=wait result.json();
    const response=等待导入(url);
    setTimeout(函数(){
    setData(响应);
    },延误);
    };
    fetchData();
    },[url]);
    返回数据;
    };
    函数App(){
    const[person,setPerson]=useState();
    const[job,setJob]=useState();
    const[collegues,setCollegues]=useState();
    //首先,我们最有可能基于jwt获取person/api/person
    const personData=useFetch(“./person.json”,5000);
    //现在我们有了person数据,我们使用id来查询
    //人员职务/api/人员/1/职务
    const jobData=useFetch(“./job.json”,3000);
    //现在我们可以在job x/api/person/1/job/1/collegues处查询人员同事
    const colleguesData=useFetch(“./collegues.json”,1000);
    console.log(personData);
    console.log(jobData);
    控制台日志(收集数据);
    //useffect(()=>{
    //setPerson(useFetch(“./person.json”,5000));
    // }, []);
    //useffect(()=>{
    //setJob(useFetch(“./job.json”,3000));
    //},[人];
    //useffect(()=>{
    //setCollegues(useFetch(“./collegues.json”,1000));
    //[工作];
    返回(
    你好,代码沙盒
    开始编辑,看看神奇的发生!
    );
    }
    const rootElement=document.getElementById(“根”);
    render((您可能需要更改空格或删除分号以使其工作)

    希望这样的事情(或者更好的解决方案)是可能的,否则我将无法从令人敬畏的redux saga/thunks迁移到context+挂钩


    最佳答案:

    钩子不会取代处理异步操作的方式,它们只是对您过去所做的一些事情的抽象,比如调用
    组件didmount
    ,或者处理
    状态
    ,等等

    在您给出的示例中,您实际上不需要自定义挂钩:

    函数应用程序(){
    const[data,setData]=useState(null);
    useffect(()=>{
    const fetchData=async()=>{
    const job=等待导入(“./job.json”);
    const collegues=等待导入(“./collegues.json”);
    const person=等待导入(“./person.json”);
    设置数据({
    工作,
    学院,
    人
    })
    };
    fetchData()
    }, []);
    返回{JSON.stringify(data)};
    }
    
    也就是说,如果您提供了一个实际的redux saga或thunks代码的示例,您希望重构,我们可以看到实现这一点的步骤

    编辑:

    也就是说,如果你还想做这样的事情,你可以看看这个:

    从“React”导入React;
    从'react hooks async/dist/use async task fetch'导入{useFetch};
    const UserInfo=({id})=>{
    常量url=`https://reqres.in/api/users/${id}?延迟=1`;
    const{pending,error,result,abort}=useFetch(url);
    如果(待定)返回加载…中止;
    if(error)返回错误:{error.name}{'}{error.message};
    如果(!result)不返回结果;
    返回名字:{result.data.First_Name};
    };
    常量应用=()=>(
    );
    
    编辑


    这是一种有趣的方法

    这是现实生活中常见的场景,您希望等待第一次提取完成,然后执行下一次提取

    请查看新的代码沙盒:

    当您执行提取请求时,我使用了generator。按照正确的顺序检索数据。单击“提取数据”按钮后,转到控制台并进行查看


    希望这就是您想要的。

    我相信您会面临这个问题,因为fetch hook的实现很差,而且这个示例太简单,我们无法理解。您应该清楚地说明是否将job、collegues和person放在同一个组件中。如果是这样的话,它就是
    import React from 'react';
    
    import { useFetch } from 'react-hooks-async/dist/use-async-task-fetch';
    
    const UserInfo = ({ id }) => {
      const url = `https://reqres.in/api/users/${id}?delay=1`;
      const { pending, error, result, abort } = useFetch(url);
      if (pending) return <div>Loading...<button onClick={abort}>Abort</button></div>;
      if (error) return <div>Error:{error.name}{' '}{error.message}</div>;
      if (!result) return <div>No result</div>;
      return <div>First Name:{result.data.first_name}</div>;
    };
    
    const App = () => (
      <div>
        <UserInfo id={'1'} />
        <UserInfo id={'2'} />
      </div>
    );
    
    const { loading, error, value } = useResource<Person>(getPerson, personId)