更新后无法访问计数器

时间:2019-10-22 16:31:59

标签: javascript reactjs react-native react-hooks

我想通过单击一个按钮来启动interval。 此处interval开始,但是我无法访问counter的值。因为当计数器等于5时,应该停止间隔。

这里是示例:

let interval = null;
const stateReducer = (state, value) => value;

function App(props) {

  const [counter, setCounter] = useReducer(stateReducer, 0);

  const increment = () => {

    interval = setInterval(() => {
      setCounter(counter + 1);
      if (counter === 5) clearInterval(interval);
      console.log(counter);
    }, 1000);

  };

  return (
    <div>
      <p>{counter}</p>
      <button className="App" onClick={increment}>
        Increment
      </button>
    </div>
  );
}

您可以在codesandbox

上运行此代码

3 个答案:

答案 0 :(得分:1)

import React, { useReducer, useEffect, useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";

let interval = null;
let current_counter = 0;
const stateReducer = (state, value) => value;

function App(props) {
  const [status, setStatus] = useState(false);
  const [counter, setCounter] = useReducer(stateReducer, 0);
  useEffect(()=>{
    if(status){
      const interval = setInterval(() => {
          setCounter(counter + 1);
        }, 1000)
        return ()=>{
          clearInterval(interval)
        };
    }

  })
  const increment = () => {
    setStatus(!status)
  };

  return (
    <div>
      <p>{counter}</p>
      <button className="App" onClick={increment}>
        Increment
      </button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

答案 1 :(得分:1)

  1. const stateReducer = (state, value) => value;更改为const stateReducer = (state, value) => state+value;
  2. 在函数外部创建变量let current_counter = 0;
  3. 像这样更改增量功能
current_counter = counter;
const increment = () => {
   interval = setInterval(() => {
      setCounter(1);
      if (current_counter === 5) clearInterval(interval);
      console.log(current_counter);
    }, 1000);
};
  1. Done

答案 2 :(得分:1)

您的代码有一些问题。

您的减速器声明

const initialState = { value : 0 }

const reducer = (state, action) =>{
    if(action.type === 'INCREMENT') return { value : state.value + 1 }

    return state
}

如何设置减速器

const [state, dispatch] = useReducer(reducer, initialState)

您如何调度动作

intervals是命令性代码,您不能在React的处理程序中始终声明interval而不用担心闭包。您只能使用click来标记该间隔应该开始并处理useEffect中的所有命令性代码。这是一个有效的例子

const initialState = { value: 0 };
const reducer = (state, action) => {
  if (action.type === "INCREMENT")
    return {
      value: state.value + 1
    };
};
function App() {
  const [state, dispatch] = React.useReducer(reducer, initialState);
  const [clicked, setClicked] = React.useState(false);

  useEffect(() => {
    let interval = null;
    if (clicked) {
      interval = setInterval(() => {
        dispatch({ type: "INCREMENT" });
      }, 1000);
    }
    if (state.value > 4) clearInterval(interval);

    return () => clearInterval(interval);
  }, [clicked, state]);

  return <button onClick={() => setClicked(true)}>{state.value}</button>;
}

Edit holy-grass-22y29

如果您对闭包以及如何处理强制命令代码感到好奇,请参阅Dan Abramov的awesome article(有关效果的最详细说明)。