将基于类的组件转换为基于功能的组件

时间:2020-05-07 07:48:20

标签: javascript react-native react-hooks

伙计们我想转换以下代码:

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = { isLoading: true };
  }

  performTimeConsumingTask = async () => {
    return new Promise((resolve) =>
      setTimeout(() => {
        resolve('result');
      }, 2000)
    );
  };

  async componentDidMount() {
    const data = await this.performTimeConsumingTask();
    if (data !== null) this.setState({ isLoading: false });
  }

  render() {

    if (this.state.isLoading) return <SplashScreen />;

    const { state, navigate } = this.props.navigation;

    return (something)

我写了这段代码,但是没用:

const App = () => {
  const [fontLoaded, setFontLoaded] = useState(false);
  const [isTimerOn, setIsTimerOn] = useState(true);

  if (!fontLoaded) {
    return (
      <AppLoading
        startAsync={fetchFonts}
        onFinish={() => setFontLoaded(true)}
      />
    );
  }
  useEffect(async () => {
    const data = await performTimeConsumingTask();
    if (data !== null) setIsTimerOn(false);
  });
  if (isTimerOn) return <SplashScreen />;
  else {
    return (something)

这将显示一个错误: Invariant Violation: Rendered More Hooks than during the previous render.

如果我评论了useEffect钩子,它将运行splashScreen。有人可以帮我转换吗?

2 个答案:

答案 0 :(得分:0)

在使用所有钩子之前,必须没有条件返回,如果您使用useEffect,则必须返回。

useEffect也不能在每个渲染器上运行,因为它会根据您的情况设置状态。因为只希望它在初始渲染上运行,所以将一个空数组作为第二个参数。

useEffect回调函数也不能异步。

在文档中详细了解useEffect挂钩。

在下面检查更新的代码

const App = () => {
  const [fontLoaded, setFontLoaded] = useState(false);
  const [isTimerOn, setIsTimerOn] = useState(true);

  const performTimeConsumingTask = async () => {
      return new Promise((resolve) =>
         setTimeout(() => {
           resolve('result');
        }, 2000)
   );
  };
  useEffect(() => {
    async function myFunction() {
       const data = await performTimeConsumingTask();
       if (data !== null) setIsTimerOn(false);
    }
    myFunction();
  }, []); // With empty dependency it runs on initial render only like componentDidMount

  if (!fontLoaded) {
    return (
      <AppLoading
        startAsync={fetchFonts}
        onFinish={() => setFontLoaded(true)}
      />
    );
  }
  if (isTimerOn) return <SplashScreen />;
  else {
    return (something)

答案 1 :(得分:0)

如果您想将此钩子用作[],请传递componentDidMount作为参数

useEffect(async () => {
const data = await performTimeConsumingTask();
if (data !== null) setIsTimerOn(false);
}, []); 

以下是钩子列表,您可以使用钩子替换生命周期方法

https://medium.com/javascript-in-plain-english/lifecycle-methods-substitute-with-react-hooks-b173073052a

出现错误的原因是您的组件渲染了太多次,并且通过传递useEffect也在每个渲染器上运行[]会在第一次渲染时运行useEffect行为类似于componentDidMount。

还要遵循此步骤在useEffect内进行网络通话

https://medium.com/javascript-in-plain-english/handling-api-calls-using-async-await-in-useeffect-hook-990fb4ae423