useState 在自定义反应钩子内不起作用[重复]

问题描述 投票:0回答:1

我正在尝试将业务逻辑的某些部分与视图逻辑分开,为此我正在使用自定义反应挂钩,其工作原理类似于控制器。

我的组件结构

  1. 包含在子级 1 和子级 2 之间切换的切换开关的父级
  2. useCustomHook 自定义 React 钩子,可进行 api 调用并使用状态来添加加载器
  3. child2 包含从 api 调用和状态变量检索的要显示的内容,以显示加载程序调用 useCustomHook
  4. parent 还调用 useCustomHook,它在挂载时进行 api 调用。

为什么我无论花多长时间都看不到child 2内的页面正在加载

我相信当子 2 上再次调用自定义钩子时,useState 将标志设置为其默认 false

我必须如何在自定义反应钩子中使用 useState 钩子,该钩子从多个地方调用并且不将状态恢复为默认值

如果您打开 child2,

flag 永远不会为 true

这是codesandbox链接代码

这是代码

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

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

export default Child1;

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;

自定义Hook.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;
javascript reactjs react-hooks
1个回答
1
投票

如果你从App和Child2调用

useCustomHook
,你会得到两个不同的对象!

  • 从 Child2 调用
    useCustomHook
    func
  • 或者将
    flag
    从 App 传递到 Child2(使用 props 或 context)

顺便说一句。在

sleep
函数中,您忘记了解决承诺。

  const sleep = async (ms) => {
    console.log("waiting");
    await new Promise((res, rej) => {
      setTimeout(() => {
        console.log("wait over");
        res(); // important!
      }, ms);
    });
  };
© www.soinside.com 2019 - 2024. All rights reserved.