【问题标题】:Lodash delay function doesn't let me to see state inside called functionLodash 延迟函数不允许我看到被调用函数内部的状态
【发布时间】:2021-11-06 16:51:18
【问题描述】:

我正在使用 lodash 的延迟函数在特定时间段后调用我的函数 3 次,由于某种原因,我在该函数中看不到更新的 React 状态。 这可能是什么原因?

import React, { useEffect, useState } from 'react';
import Delays from './helper';
import { delay } from 'lodash';

const App = () => {
  const [progress, setProgress] = useState(0);

  console.log(progress); // Here I can see the updated state

  const testFunction = () => {
    console.log('inside function', progress); // here I can't see the updated state
  };

  useEffect(() => {
    const seconds = 40;
    const attempts = 3;
    const milliseconds = 4000;

    setInterval(() => {
      setProgress((prevProgress) =>
        prevProgress >= 100 ? 100 : prevProgress + 1
      );
    }, seconds * attempts * 10); // 1200

    for (let i = 0; i < attempts; i++) {
      delay(testFunction, milliseconds * (i + 1));
    }
  }, []);
  return <div>Hello World</div>;
};

export default App;

对我来说奇怪的是,如果我使用基于类的方法,那么我没有任何问题,并且状态的值将出现在我的函数中。

import React, { Component } from 'react';
import Delays from './helper';
import { delay } from 'lodash';

class App extends Component {
  state = {
    progress: 0,
  };

  udpateProgress = (value) => {
    this.setState({ progress: value });
  };

  testFunction = () => {
    console.log('inside function', this.state.progress); // here I can see the Updated state
  };

  componentDidMount = () => {
    const seconds = 40;
    const milliseconds = 4000;
    const attempts = 3;

    setInterval(() => {
      this.udpateProgress(
        this.state.progress >= 100 ? 100 : this.state.progress + 1
      );
    }, seconds * attempts * 10); // 1200

    for (let i = 0; i < attempts; i++) {
      delay(this.testFunction.bind(this), milliseconds * (i + 1));
    }
  };

  render() {
    console.log('inside render', this.state.progress);
    return <div>Hello World</div>;
  }
}

export default App;

【问题讨论】:

    标签: reactjs react-hooks lodash use-effect use-state


    【解决方案1】:

    问题

    这里的问题是您已经关闭了 testFunction 中的初始 progress 状态值,您正在从在组件安装上运行一次的 useEffect 循环过来。

    解决方案

    一种解决方案可能是使用 React ref 来保存当前状态值,然后您可以在 testFunction 中引用它。

    function App() {
      const [progress, setProgress] = useState(0);
      const progressRef = useRef(); // <-- ref to hold state value
    
      const testFunction = () => {
        console.log('inside function', progressRef.current); // <-- reference state value
      };
      
      useEffect(() => {
        console.log(progress); // <-- log per update
        progressRef.current = progress; // <-- cache state value
      }, [progress])
    
      useEffect(() => {
        const seconds = 40;
        const attempts = 3;
        const milliseconds = 4000;
    
        const timer = setInterval(() => { // <-- don't forget to save ref to interval timer
          setProgress((prevProgress) =>
            prevProgress >= 100 ? 100 : prevProgress + 1
          );
        }, seconds * attempts * 10); // 1200
    
        for (let i = 0; i < attempts; i++) {
          delay(testFunction, milliseconds * (i + 1));
        }
    
        return () => clearInterval(timer); // <-- to clear when component unmounts!!!
      }, []);
      return <div>Hello World</div>;
    }
    

    【讨论】:

    • 这是一个很好的解决方案。请问您的意见,为什么我在基于类的方法中没有同样的问题?
    • @Sonny49 基本上是因为类组件与函数组件的 Javascript 封装没有相同的问题(因为它们是函数)。 this.state.progress 将始终是对当前状态值的引用。这样,类组件更像是对象有一个实例,而函数组件是函数并且是无实例的,它们在每次渲染时都会“重新创建”,并且只保留引用,例如我在初始渲染中提到的状态和函数循环。
    猜你喜欢
    • 2020-06-26
    • 1970-01-01
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    • 1970-01-01
    相关资源
    最近更新 更多