Gatsby 不会用反应钩子改变状态

Posted

技术标签:

【中文标题】Gatsby 不会用反应钩子改变状态【英文标题】:Gatsby don't change state with react hooks 【发布时间】:2020-05-18 16:00:37 【问题描述】:

我为我的 gatsby 网站创建了一个组件。 我想为它写一个简单的切换功能:

import React,  useState  from "react"
import './css/header.css'

function clicker(state) 
   console.log(state);


const header = () => 

const [isExpanded, toggleExpansion] = useState(false)

return (

    <div>
        <nav className="main-nav">
            <div className='container container-wide'>

                /* responsive toggle */
                <div className="block lg:hidden">
                    <button onClick=() => clicker(!isExpanded)
                        className="flex items-center px-3 py-2 border rounded text-teal-200 border-teal-400 hover:text-white hover:border-white">
                        <svg className="fill-current h-3 w-3" viewBox="0 0 20 20"
                            xmlns="http://www.w3.org/2000/svg"><title>Menu</title>
                            <path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z" />
                        </svg>
                    </button>
                </div>

                /* Main Menu*/
                <div className=`$isExpanded ? `block` : `hidden` w-full lg:flex lg:items-center lg:w-auto justify-end`  >
                    <div className="text-sm lg:flex-grow">
                        <a href="#responsive-header"
                            className="block mt-4 lg:inline-block lg:mt-0 text-teal-lightest hover:text-white mx-6">
                            Docs
                            </a>
                        <a href="#responsive-header"
                            className="block mt-4 lg:inline-block lg:mt-0 text-teal-lightest hover:text-white mx-6">
                            Examples
                            </a>
                        <a href="#responsive-header"
                            className="block mt-4 lg:inline-block lg:mt-0 text-teal-lightest hover:text-white mx-6">
                            Blog
                            </a>
                    </div>
                </div>
            </div>
        </nav>
    </div>
)

导出默认标头;

问题是:状态似乎在那里。 当我单击链接时,clicker(state) 功能会返回, 无论初始状态是什么。

但是toggleExpansion 函数并不能简单地工作或触发。 或者……组件没有按照新的状态渲染……

我不知道。 有人可以帮忙吗?

当我使用类组件时,它可以正常工作 - 有人可以告诉我为什么吗?

【问题讨论】:

【参考方案1】:

首先,您应该按照React Docs 中的建议将组件的名称大写。第二件事是您应该将事件处理程序逻辑移动到您的 Header 组件中,因为它属于该组件。 为了触发状态更改,请修复事件处理程序中的代码,如下面的代码所示。

从您的代码中,我还看到您可能还遗漏了有关 React Hooks 的另一个重要概念。请注意,在任何特定的渲染中,道具和状态永远保持不变,并且每个渲染都有自己的事件处理程序。您的事件处理程序仅 'see''close over(see closures)' state 和 props 的值为其特定的渲染。因此,控制台在事件处理程序中记录状态将始终为您提供特定渲染的状态。对 setToggleExpansion 的调用仅使用更新的状态和它自己的事件处理程序再次调用您的函数组件。

希望对您有所帮助。

const Header = () => 

  const [isExpanded, setToggleExpansion] = useState(false)

  // event handler
  function clicker() 
   console.log(isExpanded);            // logs false for the initial render
   setToggleExpansion(prev => !prev);
   console.log(isExpanded);            // logs false for the initial render
  

  return (
    <button onClick=clicker
     //...
    </button>
  )

【讨论】:

这是个错误。大写字母。谢谢你。 原来工作的那个在缓存中。没有任何效果。甚至 react.js 站点上带有计数器的示例代码也无法正常工作。状态只是不更新​​。 reactjs.org/docs/hooks-state.html 似乎有什么东西破坏了我的网站。但是控制台什么也没显示。【参考方案2】:

首先你的组件名称应该以大写字母开头React recommended 只需将其更改为Header

其次,像这样改变你的切换功能:

const Header = () => 
  const [isExpanded, toggleExpansion] = useState(false)

  return (
    <button onClick=() => toggleExpansion(!isExpanded)
     //...
    </button>
  )

要使用它,只需像这样使用&amp;&amp; logical operator:

 
   isExpanded && ( <div> ... </div> ) 


【讨论】:

以上是关于Gatsby 不会用反应钩子改变状态的主要内容,如果未能解决你的问题,请参考以下文章

组件不会重新渲染,但 redux 状态已通过反应钩子更改

反应钩子如何确定它们的组件?

如何正确更新反应钩子状态中的数组

反应钩子:新状态值未反映在 setInterval 回调中

来自 Redux 存储的数据来晚了,所以它不会填满 AG 网格表/反应钩子

提交按钮的反应钩子不改变数据