【问题标题】:Should I use state at all for a variable that does not affect rendering?我应该对不影响渲染的变量使用状态吗?
【发布时间】:2020-07-07 14:51:01
【问题描述】:
  1. 在下面的代码中,如何使status 变量的值在setStatus(!status) 之后立即改变?我知道 React 中的状态更新是批处理的,因此我使用带有回调的useEffect,但在第一次单击按钮时status 的值仍然记录为false(好像它没有立即更改)。
  2. 考虑到应用程序渲染不依赖于status 变量(实际上,我什至更希望这个变量的更改不会触发渲染),不使用@ 是不是一个不好的做法987654328@ 并将status 改为“普通”变量,像status = true 一样分配?

function App() {

  const [status, setStatus] = React.useState(false)

  React.useEffect(() => toggleStatus, [status])

  function onClickHandler() {
    toggleStatus()
    console.log(status)
  }

  function toggleStatus() {
    setStatus(!status)
  }

  return ( 
    <div>
        <button onClick={onClickHandler}>Toggle & log status</button>
    </div>
  )
}

ReactDOM.render( < App /> , document.getElementById('root'))
<script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
<div id="root"></div>

【问题讨论】:

  • 请查看brewhouse.io/blog/2015/03/24/…。用于了解何时使用状态以及何时不使用状态
  • 每当你用 setStatus 改变 status 的值,组件就会渲染,这正是 useState() 钩子的作用;

标签: javascript reactjs


【解决方案1】:
  1. 当你点击onClickHandler触发==>toggleStatusconsole.log(status)被同步触发(setStatus(!status)的toggleStatus被异步触发。所以你看到false被记录了。 并且您错误地使用了useEffectReact.useEffect(() =&gt; toggleStatus, [status]) 表示useEffect 返回toggleStatus 函数的第一个参数,即cleanup action of useEffect

试试这个以查看记录的状态

React.useEffect(() =>{
  //you can see true after first click here
  console.log(status)
}, [status])
  1. 如果您想立即更改 status 并且不重新渲染组件,您可以改用 useRef

【讨论】:

    【解决方案2】:

    我会评论你的代码

    function App() {
    
      const [status, setStatus] = React.useState(false)
    
      React.useEffect(() => toggleStatus, [status]) // here you are toggle the status again when the status change 
    
      function onClickHandler() {
        toggleStatus()
        console.log(status)
      }
    
      function toggleStatus() {
        setStatus(!status) // here you can do setStatus(prevStatus => !prevStatus)
      }
    
      return ( 
        <div>
            <button onClick={onClickHandler}>Toggle & log status</button>
        </div>
      )
    }
    
    ReactDOM.render( < App /> , document.getElementById('root'))
    <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
    <div id="root"></div>

    您可以尝试在 useEffect 中使用 console.log(status) 看看是否一切正常。

    React.useEffect(() => console.log(status), [status])
    

    现在谈第二点,我认为这不是一个坏习惯。根据 React docs:

    状态包含特定于该组件的可能更改的数据 随着时间的推移。 [...] 如果你不在 render() 中使用它,它不应该在 国家。例如,您可以将计时器 ID 直接放在 实例。

    【讨论】:

      【解决方案3】:

      React 状态用于跟踪应用程序状态并在底层状态发生变化时重新渲染应用程序。

      现在,如果您不想重新渲染,当status 更改时,您应该将status 声明为常规变量。

      如果你愿意,你仍然可以使用useEffect react 钩子。你可以在这里初始化statususeEffect 被称为组件在浏览器 DOM 上安装/渲染

      【讨论】:

        【解决方案4】:

        在下面的代码中,如何让status变量的值在setStatus(!status)之后立即改变?

        您不能立即更改状态,因为更改状态是异步的。

        我什至希望此变量的更改不会触发渲染),完全不使用useEffect 并将状态设置为“正常”变量,像状态 = true 一样分配是否是不好的做法?

        首先,检查what are the use cases for useEffect

        关于改为“正常”变量,这确实是一种不好的做法:

        const Component = () => {
           let variable = ...;
           return <>...</>
        }
        

        这是因为,在每次渲染时,这些变量都会重新分配(因为函数组件的主体会在每次渲染时执行)。 通常,这不是期望的行为。

        相反,您想使用带有useRef 的引用。见what is the difference between useRef and a variable.

        更改参考值不会触发渲染,因此不会更新 UI。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多