Гэтсби не меняет состояние с помощью реактивных крючков - PullRequest
0 голосов
/ 02 февраля 2020

Я создал компонент для своего сайта в Гэтсби. И я хотел написать для него функцию простого переключения:

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 (состояние) возвращает, каким бы ни было начальное состояние.

Но функция toggleExpansion просто не работает и не запускается. Или ... компонент не отображается в соответствии с новым состоянием ..

Я не знаю. Может ли кто-нибудь помочь?

Когда я использую компонент класса, он работает нормально - кто-то может сказать, почему?

Ответы [ 2 ]

1 голос
/ 03 февраля 2020

Прежде всего, вы должны сделать заглавными буквы названия вашего компонента, как рекомендовано в React Docs . Во-вторых, вы должны переместить свой обработчик событий logi c в ваш компонент Header, поскольку он принадлежит этому компоненту. Для того чтобы вызвать изменение состояния, исправьте код в вашем обработчике событий, как показано в коде ниже.

Из вашего кода я также вижу, что вы также можете упустить другую важную концепцию о React Hooks. Обратите внимание, что внутри любого конкретного рендера реквизиты и состояния всегда остаются прежними, и что у каждого рендера есть свои собственные обработчики событий. Ваши обработчики событий только 'see' или 'close over (смотрите замыкания)' значения состояния и реквизиты для его конкретного рендера , Поэтому консоль, регистрирующая состояние внутри вашего обработчика событий, всегда будет сообщать вам состояние для конкретного рендера. Вызов 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>
  )
}
1 голос
/ 03 февраля 2020

Сначала имя вашего компонента должно начинаться с заглавной буквы, как Рекомендуется реагировать Просто измените его на Header

Во-вторых, измените свою функцию переключения следующим образом:

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

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

И чтобы использовать его, просто используйте && логический оператор , например:

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

Edit long-star-0ob0w

...