Reactjs React/Redux只需单击一次即可执行多个转介

Reactjs React/Redux只需单击一次即可执行多个转介,reactjs,redux,react-redux,Reactjs,Redux,React Redux,当我添加constservertime=useSelector(state=>state.serverTime)时,当我单击一次时,分派会发生多次。但是当我删除constservertime=useSelector(state=>state.serverTime)时,这个问题就消失了代码。原因是什么?我做错了什么 Component.js import { useSelector, useDispatch } from "react-redux"; const Buy =

当我添加
constservertime=useSelector(state=>state.serverTime)时,当我单击一次时,分派会发生多次。但是当我删除
constservertime=useSelector(state=>state.serverTime)时,这个问题就消失了代码。原因是什么?我做错了什么

Component.js

import { useSelector, useDispatch } from "react-redux";

const Buy = () => {
    const dispatch = useDispatch();
    const serverTime = useSelector(state => state.serverTime);

    document.body.addEventListener("click", function() {
        dispatch(SERVER_TIME(Date.now()))
    })

    return (
        <main>
           ...
        </main>
    )
}

Reducer.js

let initialState = {
    serverTime: ""
}

const serverTime = (state = initialState, action) => {
    switch (action.type) {
        case "SERVER_TIME":
            return {
                ...state,
                serverTime: action.serverTime
            }
        default:
            return state
    }
}

export default serverTime;

问题并非真正的
serverTime
,尽管这会引发问题。真正的问题是如何设置事件侦听器

Buy
组件中,每次更新组件时都要添加事件侦听器,而不是只更新一次。因此,每当状态发生变化时(如每当更新服务器时间时),react都会添加另一个事件侦听器。要仅添加一个事件侦听器,您应该将其包装在
Buy
组件中

useffect
的第一个参数是要在第一次渲染时运行的函数,第二个参数是依赖项数组,当这些依赖项发生更改时,将触发该函数的重新运行。在您的情况下,因为您只希望此操作运行一次,所以可以使用空数组,这样就不会触发重新运行

useffect
中的函数参数也可以返回一个函数,该函数将在卸载组件时用于“清理”。这对于取消订阅事件侦听器非常有用。例如:

useEffect( () => {
  // Define what should happen on click.
  function onClickStuff(){
      dispatch(SERVER_TIME(Date.now()))
  }
  // Add the event listener to the document.
  document.body.addEventListener("click", onClickStuff)
  return () => {
    // Remove the event listener on unmount.
    document.body.removeEventListner("click", onClickStuff)
  }
}, [] /* No dependencies, so useEffect will only run once. */ )

问题并非真正的
serverTime
,尽管这会引发问题。真正的问题是如何设置事件侦听器

Buy
组件中,每次更新组件时都要添加事件侦听器,而不是只更新一次。因此,每当状态发生变化时(如每当更新服务器时间时),react都会添加另一个事件侦听器。要仅添加一个事件侦听器,您应该将其包装在
Buy
组件中

useffect
的第一个参数是要在第一次渲染时运行的函数,第二个参数是依赖项数组,当这些依赖项发生更改时,将触发该函数的重新运行。在您的情况下,因为您只希望此操作运行一次,所以可以使用空数组,这样就不会触发重新运行

useffect
中的函数参数也可以返回一个函数,该函数将在卸载组件时用于“清理”。这对于取消订阅事件侦听器非常有用。例如:

useEffect( () => {
  // Define what should happen on click.
  function onClickStuff(){
      dispatch(SERVER_TIME(Date.now()))
  }
  // Add the event listener to the document.
  document.body.addEventListener("click", onClickStuff)
  return () => {
    // Remove the event listener on unmount.
    document.body.removeEventListner("click", onClickStuff)
  }
}, [] /* No dependencies, so useEffect will only run once. */ )