#2 React - локальный стейт

poster
В этом уроке мы разберемся что такое локальный стейт в React. Напишем с его помощью выпадающее меню. Разберемся какие сложности бывают с вызовом методов класса.
Понравилось? Поделитесь с друзьями!
Понравилось?
Поделитесь с друзьями!
Комментарии
Текст видео

Всем привет. Сегодня мы поговорим о типах данных в реакт. У реакта есть 2 типа данных - это props и state. В этом уроке мы разберем что такое локальный стейт и как с ним работать в react.

Если вам нужно чтобы какие то изменения происходили только внутри конкретной компоненты, то всегда стоит использовать локальный стейт.

Давайте попробуем. И первое, что мы будем реализовывать это выпадающее меню.

Давайте создадим новый компонент Dropdown.js

import React, { Component } from 'react';

class Dropdown extends Component {
  render() {
    return <div>Its dropdown baby</div>;
  }
}

export default Dropdown;

Теперь нам нужно этот компонент заимпортить в App.js и вывести на экран.

import React, { Component } from 'react';

import Dropdown from './Dropdown.js';

class App extends Component {
  render() {
    return (
      <div>
        <Dropdown />
      </div>
    );
  }
}

export default App;

Нужно всегда помнить 2 вещи:

  1. Если мы хотим, чтобы return в render методе был многострочный нужно оборачивать все, что мы хотим вернуть в круглые скобки.
  2. Возвращать всегда можно только 1 елемент. То есть вы не можете написать 2 дива на одном уровне. Чтобы это работало вам прийдется обернуть их еще в 1 див.

В браузере мы видим, что наш компонент вывелся на экран.

Давайте добавим переменную в стейт при инициализации компонента. Для этого мы просто добавляем constructor в класс.

import React, { Component } from 'react';

class Dropdown extends Component {
  constructor(props) {
      super(props);
      this.state = { isOpened: false };
  }

  render() {
    return <div>Its dropdown baby</div>;
  }
}

export default Dropdown;

Нужно не забывать вызывать метод super при инициализации так как переопределяя конструктор, нам нужно не сломать приложение. Здесь при просто при инициализации компонента создали переменную isOpened в стейте и поставили ее в false;

Давайте добавим onClick событие и метод, который будет туглить isOpened переменную

import React, { Component } from 'react';

class Dropdown extends Component {
  constructor(props) {
      super(props);
      this.state = { isOpened: false };
  }

  toggleState() {
    this.setState({ isOpened: !this.state.isOpened });
  }

  render() {
    console.log('isOpened', this.state.isOpened);
    return <div onClick={this.toggleState}>Its dropdown baby</div>;
  }
}

export default Dropdown;

Обратите внимание, что в onClick метод передается без вызова, т.е. без круглых скобок иначе он вызовется сразу.

В toggleState мы вызываем метод setState, который позволяет нам менять стейт.

В консоли мы видим, что по умолчанию isOpened = false. Если же мы кликнем на текст, то мы видим ошибку

Dropdown.js:37 Uncaught TypeError: Cannot read property 'setState' of null

Это случается потому что функция this.toggleState вызывается не в контексте класса и поэтому this является undefined.

Чтобы заставить наш код работать давайте прибиндим его к this

render() {
  console.log('isOpened', this.state.isOpened);
  return <div onClick={this.toggleState.bind(this)}>Its dropdown baby</div>;
}

Как мы видим в консоли теперь значение меняется при клике на блок.

Давайте немного изменим разметку, чтобы у нас действительно появлялся блок на клик.

render() {
  console.log('isOpened', this.state.isOpened);
  let dropdownText;
  if (this.state.isOpened) {
    dropdownText = <div>Here is what is shown in dropdown</div>;
  }
  return (
    <div onClick={this.toggleState.bind(this)}>
      Its dropdown baby
      {dropdownText}
    </div>
  );
}

Здесь мы сетим в переменную dropdownText значение, когда у нас isOpened = true. И выводим переменую в фигурных скобках.

Как мы видим в браузере у нас появляется и скрывается блок по клику.

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
Petr Pozhoga
14 дней назад
Здравствуйте, столкнулся с задачей как поменять стейт если у тебя большая вложеность ? Например: formValidate: { error: [ { errorMail: false }, { errorPassword: false }, { errorAuth: false } ], errorFormMessage: '', } И здесь я хочу поменять свойство errorMail, (использовать буду редакс, хранить в стейте такое не буду, просто интересно)
monsterlessons
14 дней назад
Добрый день. Большая вложенность, это всегда плохо тк усложняет обновление данных. Я для операций с данными использую ramda (на js это было бы куча кода) R.assocPath(['formValidate', 'error', 'errorAuth'], true, state)
Petr Pozhoga
1 месяц назад назад
Возможно будет полезно не только мне! Зада -> Есть 1 парент компонетнт и 2 чайлд, в этих 2 компонента мне надо прокидывать данные с стейта в первый прокидываю просто массив в второй отсортированный, но отсортированный со временем будет меняться, и по логике React у меня должен быть один массив, так как в 12 пункте Docs сказано, что вычислительно свойство(например отсортированный массив) нельзя хранить в стейте, что посоветуете ?
monsterlessons
1 месяц назад назад
Хранить исходный массив в паренте и передавать в чайлды. Кому и что нужно менять, то пусть меняют у себя внутри. Менять в паренте нужно только если это данные должны измениться более чем в одном чайлде. P.S. здесь нет серебрянной пули и стандарта и у реакта нет документации, что нужно хранить только 1 массив. Храните так, как вам и вашему проекту удобно.
Moe Green
11 месяцев назад
а зачем использовать такую громоздкую конструкцию через constructor() для инициализации state? почему не проще сделать так - state = { isOpened: false } ?
monsterlessons
11 месяцев назад
Можно и так, но это ес7, а не ес6.
Moe Green
11 месяцев назад
я Вас понял )
Moe Green
11 месяцев назад
и вот еще - toggleState = () => { const currState = this.state.isOpened this.setState({ isOpened: !currState }) } может быть в таких случаях лучше использовать стрелочные функции?
Altynbek
1год назад назад
this.setState({ isOpened: !this.state.isOpened }); -> it's bad way, change and use prevState
monsterlessons
1год назад назад
Почему это плохой способ? Я согласен, что этот код можно написать и через prevState, но по производительности оба варианта одинаковы.
Altynbek
1год назад назад
setState асинхронный. React не сразу делает обновление state, он смотрить есть ли другие изменения. И вы не знаете каким будет ваш state, когда вы вызовите setState.
monsterlessons
1год назад назад
Хмм... возможно. Я всегда использовал this.state и багов не ловил. Но думаю вы правы.
Moe Green
11 месяцев назад
у меня тот же вопрос возник. я видел туториал, где тоже используют промежуточную переменную