简体   繁体   English

useState 在自定义反应挂钩中不起作用

[英]useState not working inside a custom react hook

I am Trying to separate some part of my business logic from view logic for this I am employing the use of custom react hooks which works like a controller.我正在尝试将我的业务逻辑的某些部分与视图逻辑分开,为此我正在使用自定义反应挂钩,其工作方式类似于 controller。

My Component Structure我的组件结构

  1. Parent that contains toggle to switch between child 1 and child 2父级包含用于在子级 1 和子级 2 之间切换的开关
  2. useCustomHook custom react hook that makes an api call and uses a state to add a loader useCustomHook 自定义 react hook,调用 api 并使用 state 添加加载程序
  3. child2 contains content to be shown which was retrieved from api call and state variable to show loader calls useCustomHook child2 包含要显示的内容,这些内容是从 api 调用和 state 变量中检索到的,以显示加载程序调用 useCustomHook
  4. parent also calls useCustomHook which makes the api call on mount. parent 还调用 useCustomHook,它在挂载时调用 api。

Why can't I see loading on the page inside child 2 no matter how long it takes为什么无论需要多长时间,我都看不到 child 2 页面上的加载

I believe useState is setting flag to its default false when custom hook is called again on child 2我相信当在子 2 上再次调用自定义挂钩时,useState 将标志设置为其默认 false

What way do i have to make use of useState hook in a custom react hook which is called from more than one place and not have the state reverted back to default value我必须如何在自定义反应挂钩中使用 useState 挂钩,该挂钩从多个地方调用并且没有将 state 恢复为默认值

flag is never true if you open child2如果您打开 child2,标志永远不会为真

Here is the codesandbox link code这是codesandbox链接代码

Here is the code这是代码

App.js acts as parent App.js 作为父母

import "./styles.css";
import Child1 from "./Child1";
import Child2 from "./Child2";
import { useEffect, useState } from "react";
import useCustomHook from "./customHook";
import { makeStyles } from "@material-ui/core";

const useStyles = makeStyles((theme) => {
  return {
    parent: {
      padding: "10px"
    },
    toggle: {
      margin: "10px",
      border: "1px solid black",
      display: "flex",
      justifyContent: "space-around"
    },
    child: {
      border: "1px solid black",
      width: "50%"
    }
  };
});

export default function App() {
  const [isChild1, setIsChild1] = useState(true);
  const classes = useStyles();
  const { flag, func } = useCustomHook();

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

  return (
    <div className="App">
      <div className={classes.parent}>Parent</div>
      <div className={classes.toggle}>
        <div
          onClick={() => {
            setIsChild1(true);
          }}
          className={classes.child}
        >
          ch1
        </div>
        <div
          onClick={() => {
            setIsChild1(false);
          }}
          className={classes.child}
        >
          ch2
        </div>
      </div>
      {isChild1 ? <Child1 /> : <Child2 />}
    </div>
  );
}

Child1.js Child1.js

const Child1 = () => {
  return <div>Child1</div>;
};

export default Child1;

Child2.js Child2.js

import useCustomHook from "./customHook";

const Child2 = () => {
  const { flag } = useCustomHook();

  console.log('flag ',flag);
  return (
    <div>
      <div>Child2</div>
      <div>{flag ? "loading..." : "content"}</div>
    </div>
  );
};

export default Child2;

CustomHook.js CustomHook.js

import { useState } from "react";

const useCustomHook = () => {
  const [flag, setFlag] = useState(false);

  const sleep = async (ms) => {
    console.log("waiting");
    await new Promise((res, rej) => {
      setTimeout(() => {
        console.log("wait over");
      }, ms);
    });
  };
  const func = async () => {
    setFlag(true);

    //do some work like api call
    await sleep(10000);

    setFlag(false);
  };

  return { flag, func };
};

export default useCustomHook;

If you call useCustomHook from App and Child2, you get two different objects!如果你从 App 和 Child2 调用useCustomHook ,你会得到两个不同的对象!

  • Either call useCustomHook and func from Child2,从 Child2 调用useCustomHookfunc
  • Or pass down flag from App to Child2 (using props or context)或者将flag从 App 传递给 Child2(使用道具或上下文)

Btw.顺便提一句。 in the sleep function you forgot to resolve the promise.sleep function 你忘了解析 promise。

  const sleep = async (ms) => {
    console.log("waiting");
    await new Promise((res, rej) => {
      setTimeout(() => {
        console.log("wait over");
        res(); // important!
      }, ms);
    });
  };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM