Що таке useState () в React?


134

В даний час я вивчаю концепцію гачків в React і намагаюся розібратися нижче на прикладі.

import { useState } from 'react';

function Example() {
    // Declare a new state variable, which we'll call "count"
    const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Наведений вище приклад збільшує лічильник на сам параметр функції обробника. Що робити, якщо я хочу змінити значення лічильника у функції обробника подій

Розглянемо нижче приклад

setCount = () => {
  //how can I modify count value here. Not sure if I can use setState to modify its value
  //also I want to modify other state values as well here. How can I do that
}

<button onClick={() => setCount()}>
  Click me
</button>

Ви також можете подивитися у вихідному коді, щоб зрозуміти, як useStateреалізується. Ось визначення щодо версії 16.9 .
chemturion

Відповіді:


148

Реакційні гачки - це новий спосіб (ще розробляється) для доступу до основних функцій реагування, таких як stateбез використання класів, у вашому прикладі, якщо ви хочете збільшити лічильник безпосередньо у функції обробника, не вказуючи його безпосередньо в onClickопорі, ви міг зробити щось на кшталт:

...
const [count, setCounter] = useState(0);
const [moreStuff, setMoreStuff] = useState(...);
...

const setCount = () => {
    setCounter(count + 1);
    setMoreStuff(...);
    ...
};

та onClick:

<button onClick={setCount}>
    Click me
</button>

Давайте швидко пояснимо, що відбувається в цьому рядку:

const [count, setCounter] = useState(0);

useState(0)повертає кортеж, де першим параметром countє поточний стан лічильника і setCounterце метод, який дозволить нам оновити стан лічильника. Ми можемо використовувати setCounterметод для оновлення стану в countбудь-якому місці - У цьому випадку ми використовуємо його всередині setCountфункції, де ми можемо робити більше речей; ідея гачків полягає в тому, що ми можемо зберегти наш код більш функціональним і уникнути компонентів на основі класу, якщо не потрібно / не потрібно.

Я написав статтю повністю про гачках з декількома прикладами (включаючи лічильники) , такі як це codepen , я використовував useState, useEffect, useContextі призначені для користувача гачки . Я міг би детальніше розповісти про те, як працюють гачки на цю відповідь, але документація робить дуже гарну роботу, детально пояснюючи стан гачка та інші гачки, сподіваюся, що це допомагає.

оновлення: Гачки більше не є пропозицією , оскільки версія 16.8 тепер доступна для використання, на сайті React є розділ, який відповідає на деякі поширені запитання .


2
Хороша аналогія, за винятком того, що JavaScript технічно не має тип даних даних
goonerify

Ну, деструктуріровать призначення використовуються як кортеж stackoverflow.com/a/4513061/6335029
NaveenDA

Чи гачки асинхронні? При використанні setSomething, якщо я потім спробую використовувати somethingбезпосередньо після цього, здається, воно все ще має старе значення ...
Байрон Коетзе,

51

useStateє одним із вбудованих гачків для реагування, доступних у 0.16.7версії.

useStateслід використовувати лише всередині функціональних компонентів. useStateце спосіб, якщо нам потрібен внутрішній стан і не потрібно реалізовувати складніші логіки, такі як методи життєвого циклу.

const [state, setState] = useState(initialState);

Повертає значення стану та функцію його оновлення.

Під час початкового візуалізації повернутий стан (стан) є таким самим, як і значення, передане як перший аргумент (InitiState).

Функція setState використовується для оновлення стану. Він приймає нове значення стану і вимагає повторного відтворення компонента.

Зауважте, що useStateзворотний виклик гака для оновлення стану поводиться інакше, ніж компоненти this.setState. Щоб показати вам різницю, я підготував два приклади.

class UserInfoClass extends React.Component {
  state = { firstName: 'John', lastName: 'Doe' };
  
  render() {
    return <div>
      <p>userInfo: {JSON.stringify(this.state)}</p>
      <button onClick={() => this.setState({ 
        firstName: 'Jason'
      })}>Update name to Jason</button>
    </div>;
  }
}

// Please note that new object is created when setUserInfo callback is used
function UserInfoFunction() {
  const [userInfo, setUserInfo] = React.useState({ 
    firstName: 'John', lastName: 'Doe',
  });

  return (
    <div>
      <p>userInfo: {JSON.stringify(userInfo)}</p>
      <button onClick={() => setUserInfo({ firstName: 'Jason' })}>Update name to Jason</button>
    </div>
  );
}

ReactDOM.render(
  <div>
    <UserInfoClass />
    <UserInfoFunction />
  </div>
, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

Новий об'єкт створюється при setUserInfoвикористанні зворотного дзвінка. Зауважте, ми втратили lastNameключове значення. Щоб зафіксувати, що ми могли передати функцію всередині useState.

setUserInfo(prevState => ({ ...prevState, firstName: 'Jason' })

Див. Приклад:

// Please note that new object is created when setUserInfo callback is used
function UserInfoFunction() {
  const [userInfo, setUserInfo] = React.useState({ 
    firstName: 'John', lastName: 'Doe',
  });

  return (
    <div>
      <p>userInfo: {JSON.stringify(userInfo)}</p>
      <button onClick={() => setUserInfo(prevState => ({
        ...prevState, firstName: 'Jason' }))}>
        Update name to Jason
      </button>
    </div>
  );
}

ReactDOM.render(
    <UserInfoFunction />
, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

На відміну від методу setState, знайденого в компонентах класу, useState не об'єднує автоматично об’єкти оновлення. Ви можете повторити цю поведінку, поєднавши форму оновлення функцій із синтаксисом розповсюдження об'єктів:

setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

Більш детальну інформацію про useStateсм офіційної документації .


2
Дякуємо, що додали функцію як параметр у приклад.
Juni Brosas

15

Синтаксис useStateгака прямий.

const [value, setValue] = useState(defaultValue)

Якщо ви не знайомі з цим синтаксисом, перейдіть сюди .

Я рекомендую вам ознайомитися з документацією . Є чудові пояснення з пристойною кількістю прикладів.

import { useState } from 'react';

function Example() {
    // Declare a new state variable, which we'll call "count"
    const [count, setCount] = useState(0);
  
  // its up to you how you do it
  const buttonClickHandler = e => {
   // increment
   // setCount(count + 1)
   
   // decrement
   // setCount(count -1)
   
   // anything
   // setCount(0)
  }
  

  return (
       <div>
          <p>You clicked {count} times</p>
         <button onClick={buttonClickHandler}>
             Click me
         </button>
      </div>
   );
 }


Це має бути прийнятою відповіддю. Короткий і чіткий, з хорошими зовнішніми посиланнями.
varun

8

useStateє одним з гачків, доступних у React v16.8.0. Це в основному дозволяє вам перетворити ваші інакше недержавні / функціональні компоненти на ті, які можуть мати власний стан.

На самому базовому рівні він використовується таким чином:

const [isLoading, setLoading] = useState(true);

Потім це дозволяє викликати setLoadingпередачу булевого значення. Це класний спосіб мати "державний" функціональний компонент.


7

useState()є гачком Реагу. Гачки дозволяють використовувати стан та зміни функції всередині функціональних компонентів.

Хоча ви не можете використовувати гачки всередині класів, ви можете обгортати компонент класу функцією і використовувати гачки з нього. Це чудовий інструмент для переміщення компонентів з класу у форму функції. Ось повний приклад:

Для цього прикладу я буду використовувати лічильник. Це воно:

class Hello extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: props.count };
  }
  
  inc() {
    this.setState(prev => ({count: prev.count+1}));
  }
  
  render() {
    return <button onClick={() => this.inc()}>{this.state.count}</button>
  }
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'></div>

Це простий компонент класу зі станом підрахунку, і оновлення стану здійснюється методами. Це дуже поширена модель у компонентах класу. Перше, що потрібно обернути його функціональним компонентом з таким самим іменем, який делегує всі його властивості загорнутому компоненту. Також потрібно повернути завернутий компонент у повернення функції. Ось:

function Hello(props) {
  class Hello extends React.Component {
    constructor(props) {
      super(props);
      this.state = { count: props.count };
    }

    inc() {
      this.setState(prev => ({count: prev.count+1}));
    }

    render() {
      return <button onClick={() => this.inc()}>{this.state.count}</button>
    }
  }
  return <Hello {...props}/>
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'></div>

Це точно той самий компонент, з однаковою поведінкою, тим же ім’ям і тими ж властивостями. Тепер давайте піднімемо стан підрахунку до компонента функції. Це так:

function Hello(props) {
  const [count, setCount] = React.useState(0);
  class Hello extends React.Component {
    constructor(props) {
      super(props);
      this.state = { count: props.count };
    }

    inc() {
      this.setState(prev => ({count: prev.count+1}));
    }

    render() {
      return <button onClick={() => setCount(count+1)}>{count}</button>
    }
  }
  return <Hello {...props}/>
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js" integrity="sha256-3vo65ZXn5pfsCfGM5H55X+SmwJHBlyNHPwRmWAPgJnM=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js" integrity="sha256-qVsF1ftL3vUq8RFOLwPnKimXOLo72xguDliIxeffHRc=" crossorigin="anonymous"></script>
<div id='root'></div>

Зауважте, що метод incвсе ще існує, він нікому не шкодить, насправді це мертвий код. Це ідея, просто продовжуйте піднімати стан. Після закінчення ви можете видалити компонент класу:

function Hello(props) {
  const [count, setCount] = React.useState(0);

  return <button onClick={() => setCount(count+1)}>{count}</button>;
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js" integrity="sha256-3vo65ZXn5pfsCfGM5H55X+SmwJHBlyNHPwRmWAPgJnM=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js" integrity="sha256-qVsF1ftL3vUq8RFOLwPnKimXOLo72xguDliIxeffHRc=" crossorigin="anonymous"></script>

<div id='root'></div>

Хоча це дозволяє використовувати гачки всередині компонентів класу, я б не рекомендував це робити, за винятком випадків, коли ви мігруєте, як я робив у цьому прикладі. Змішування функціональних та класових компонентів зробить управління державою безладним. Я сподіваюся, що це допомагає

З найкращими побажаннями


7

useState () - це приклад вбудованого гачка React, який дозволяє використовувати стани у своїх функціональних компонентах. Це було неможливо до початку 16.7.

Функція useState - це вбудований гачок, який можна імпортувати з пакета реагування. Це дозволяє додати стан до своїх функціональних компонентів. Використовуючи гачок useState всередині функціонального компонента, ви можете створити фрагмент стану, не переходячи на компоненти класу.


5

Нова React v16.7.0-alpha useStateгачка - це гачок. useState()встановити значення за замовчуванням будь-якої змінної та керувати у компоненті функції (функції PureComponent). ex : const [count, setCount] = useState(0);встановити значення за замовчуванням лічильника 0. , і ви можете використовувати , setCountщоб incrementабо decrementзначення. onClick={() => setCount(count + 1)}приріст значення рахунку. DOC


5

Дякую loelsonk, я так і зробив

const [dataAction, setDataAction] = useState({name: '', description: ''});

    const _handleChangeName = (data) => {
        if(data.name)
            setDataAction( prevState  => ({ ...prevState,   name : data.name }));
        if(data.description)
            setDataAction( prevState  => ({ ...prevState,   description : data.description }));
    };
    
    ....return (
    
          <input onChange={(event) => _handleChangeName({name: event.target.value})}/>
          <input onChange={(event) => _handleChangeName({description: event.target.value})}/>
    )


2

useState - це гачок, що дозволяє додавати стан функціональному компоненту. Він приймає аргумент, який є початковою вартістю власності держави і повертає поточну вартість державної власності та метод, здатний оновити цю власність держави.
Наведемо простий приклад:
import React, {useState} from react
function HookCounter {
const [count, stateCount]= useState(0)
return(
<div>
<button onClick{( ) => setCount(count+1)}> count{count} </button>
</div>
)
}

useState приймає початкове значення змінної стану, яке в цьому випадку дорівнює нулю, і повертає пару значень. Поточне значення стану називається count, а метод, який може оновити змінну стану, називається setCount.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.