Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.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
Reactjs 在事件处理程序中调用自定义挂钩_Reactjs_React Hooks - Fatal编程技术网

Reactjs 在事件处理程序中调用自定义挂钩

Reactjs 在事件处理程序中调用自定义挂钩,reactjs,react-hooks,Reactjs,React Hooks,我有一个名为useFetchMyApi的定制钩子,它将一个获取调用包装到API端点。函数钩子接受一个参数,它包含在post主体中。数据数组输出取决于hook参数 在UI上,应用程序组件调用一次useFetchMyApi。按钮点击处理程序将调用后续的useFetchMyApi,以更新UI上的列表 我的问题: 我无法在事件处理程序中调用useFetchMyApi,因为它违反了hook的规则 如何根据useFetchMyApi的响应刷新项目列表 import React,{useState,useff

我有一个名为
useFetchMyApi
的定制钩子,它将一个获取调用包装到API端点。函数钩子接受一个参数,它包含在post主体中。数据数组输出取决于hook参数

在UI上,应用程序组件调用一次
useFetchMyApi
。按钮点击处理程序将调用后续的
useFetchMyApi
,以更新UI上的列表

我的问题:

  • 我无法在事件处理程序中调用
    useFetchMyApi
    ,因为它违反了hook的规则
  • 如何根据
    useFetchMyApi
    的响应刷新项目列表
  • import React,{useState,useffect,useRef}来自“React”;
    导入“/styles.css”;
    const useFetchMyApi=(location=”“)=>{
    const[items,setItems]=useState([]);
    useffect(()=>{
    //让我们用2秒的响应时间来刺激API调用
    setTimeout(()=>setItems([location,Math.random()]),5000);
    },[地点];
    返回{items};
    };
    导出默认函数App(){
    const locationSelect=useRef(null);
    const{items}=useFetchMyApi(“mylocation1”);
    const onButtonClicked=(事件)=>{
    const selectedLocation=locationSelect.current.value;
    //调用api并按位置刷新项目
    //在这里修好??
    //useFetchMyApi(selectedLocation);
    };
    返回(
    地点1
    地点2
    刷新
    
      {items.map((item)=>(
    • {item}
    • ))}
    ); }

    问题
  • 我无法在事件处理程序中调用
    useFetchMyApi
    ,因为它违反了挂钩规则
  • 正确,只能从功能组件体和其他react钩子调用react钩子。不能有条件地调用它们,例如在异步回调或循环中

  • 如何根据
    useFetchMyApi
    的响应刷新项目列表
  • App
    中,您没有任何东西可以触发重新渲染器来触发效果,从而触发效果的回调

    解决方案 您应该在自定义
    useffetchmyapi
    hook中利用
    useffect
    hook的依赖项来刷新项目列表。添加一些本地组件状态以表示“当前”选定位置。使用按钮的
    onClick
    回调更新状态并触发重新加载程序,然后重新运行自定义挂钩

    const useFetchMyApi = (location = "") => {
      const [items, setItems] = useState([]);
      useEffect(() => {
        // let's stimulate the API call with a 2 seconds response time
        setTimeout(() => setItems([location, Math.random()]), 2000);
      }, [location]); // <-- effect callback triggers when location updates
      return { items };
    };
    
    function App() {
      const locationSelect = useRef(null);
      const [location, setLocation] = useState("mylocation1"); // <-- add state
      const { items } = useFetchMyApi(location); // <-- pass location value to hook
    
      const onButtonClicked = () => {
        const selectedLocation = locationSelect.current.value;
        setLocation(selectedLocation); // <-- update state, trigger rerender
      };
    
      return (
        <div className="App">
          <select ref={locationSelect}>
            <option value="location1">Location 1</option>
            <option value="location2">Location 2</option>
          </select>
          <button onClick={onButtonClicked}>Refresh</button>
          <ul>
            {items.map((item) => (
              <li>{item}</li>
            ))}
          </ul>
        </div>
      );
    }
    

    为什么不将项目声明为App`state?@thelonglqd项目列表将由自定义挂钩管理,不是吗?不能,您需要修改挂钩以返回执行获取的函数,现在挂钩取决于location参数,而不是onClick事件。感谢您提供的非常有用和详细的解释。状态驱动UI,而不是组件/挂钩。我的错误是认为挂钩可以直接影响其他组件/挂钩。
    const useFetchMyApi = (location = "") => {
      const [items, setItems] = useState([]);
      useEffect(() => {
        // let's stimulate the API call with a 2 seconds response time
        setTimeout(() => setItems([location, Math.random()]), 2000);
      }, [location]); // <-- effect callback triggers when location updates
      return { items };
    };
    
    function App() {
      const locationSelect = useRef(null);
      const [location, setLocation] = useState("mylocation1"); // <-- add state
      const { items } = useFetchMyApi(location); // <-- pass location value to hook
    
      const onButtonClicked = () => {
        const selectedLocation = locationSelect.current.value;
        setLocation(selectedLocation); // <-- update state, trigger rerender
      };
    
      return (
        <div className="App">
          <select ref={locationSelect}>
            <option value="location1">Location 1</option>
            <option value="location2">Location 2</option>
          </select>
          <button onClick={onButtonClicked}>Refresh</button>
          <ul>
            {items.map((item) => (
              <li>{item}</li>
            ))}
          </ul>
        </div>
      );
    }
    
    const useFetchMyApi = () => {
      const [items, setItems] = useState([]);
    
      // custom fetch function consumes location
      const locationFetch = (location = "") => {
        // let's stimulate the API call with a 2 seconds response time
        setTimeout(() => setItems([location, Math.random()]), 2000);
      };
      
      return [items, locationFetch]; // <-- return state and fetch function
    };
    
    export default function App() {
      const locationSelect = useRef(null);
      const [items, locationFetch] = useFetchMyApi(); // <-- destructure state and fetch function
    
      useEffect(() => {
        locationFetch("mylocation1");
      }, []); // <-- initial mounting fetch call
    
      const onButtonClicked = () => {
        const selectedLocation = locationSelect.current.value;
        locationFetch(selectedLocation); // <-- invoke fetch function
      };
    
      return (
        <div className="App">
          <select ref={locationSelect}>
            <option value="location1">Location 1</option>
            <option value="location2">Location 2</option>
          </select>
          <button onClick={onButtonClicked}>Refresh</button>
          <ul>
            {items.map((item) => (
              <li>{item}</li>
            ))}
          </ul>
        </div>
      );
    }