Я хотел бы спросить, почему мое состояние не меняется, когда я выполняю событие onClick. Некоторое время назад я искал, что мне нужно привязать функцию onClick в конструкторе, но состояние все еще не обновляется.

Вот мой код:

import React from 'react';
import Grid from 'react-bootstrap/lib/Grid';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';
import BoardAddModal from 'components/board/BoardAddModal.jsx';    
import style from 'styles/boarditem.css';

class BoardAdd extends React.Component {
    constructor(props) {
        super(props);    
        this.state = {
            boardAddModalShow: false
        };    
        this.openAddBoardModal = this.openAddBoardModal.bind(this);
    }

    openAddBoardModal() {
        this.setState({ boardAddModalShow: true }); // set boardAddModalShow to true

        /* After setting a new state it still returns a false value */
        console.log(this.state.boardAddModalShow);   
    }

    render() {    
        return (
            
                
                    
Create New Board
); } } export default BoardAdd

Ответы (15)

Этот обратный вызов действительно беспорядочный. Просто используйте вместо этого async await:

async openAddBoardModal(){
    await this.setState({ boardAddModalShow: true });
    console.log(this.state.boardAddModalShow);
}

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

_stateUpdated(){
  console.log(this.state. boardAddModalShow);
}

openAddBoardModal(){
  this.setState(
    {boardAddModalShow: true}, 
    this._stateUpdated.bind(this)
  );
}

Таким образом, вы можете вызывать метод «_stateUpdated» каждый раз, когда пытаетесь обновить состояние для отладки.

Думайте о setState () как о запросе, а не о немедленной команде для обновить компонент. Для лучшего восприятия производительности React может отложите его, а затем обновите несколько компонентов за один проход. Реагировать не гарантирует немедленное применение изменений состояния.

Проверьте здесь для получения дополнительной информации.

В вашем случае вы отправили запрос на обновление состояния. React требует времени, чтобы ответить. Если вы попытаетесь сразу console.log состояние, вы получите старое значение.

Согласно React Docs

React не гарантирует немедленного применения изменений состояния. Это делает чтение this.state сразу после вызова setState () потенциальной ловушкой и потенциально может вернуть существующее значение из-за природы async. Вместо этого используйте componentDidUpdate или обратный вызов setState, который выполняется сразу после успешного выполнения операции setState. Обычно мы рекомендуем использовать componentDidUpdate () для такой логики.

Пример:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      counter: 1
    };
  }
  componentDidUpdate() {
    console.log("componentDidUpdate fired");
    console.log("STATE", this.state);
  }

  updateState = () => {
    this.setState(
      (state, props) => {
        return { counter: state.counter + 1 };
      });
  };
  render() {
    return (
      

Hello CodeSandbox

Start editing to see some magic happen!

); } } const rootElement = document.getElementById("root"); ReactDOM.render(, rootElement);

setState () асинхронный. Лучший способ проверить, обновляется ли состояние - это componentDidUpdate (), а не помещать console.log (this.state.boardAddModalShow) после this. setState ({boardAddModalShow: true}).

согласно React Docs

Думайте о setState () как о запросе, а не как о немедленной команде для обновления компонента. Для лучшего восприятия производительности React может отложить ее, а затем обновить несколько компонентов за один проход. React не гарантирует, что изменения состояния будут применены немедленно

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

componentDidUpdate(){}

Я добавил этот метод в свой код после constructor (). ознакомьтесь с жизненным циклом рабочего процесса react native.

https://images.app.goo.gl/BVRAi4ea2P4LchqJ8

К счастью, setState () принимает обратный вызов. И здесь мы получаем обновленное состояние.

Рассмотрим этот пример.

this.setState ({name: "myname"}, () => {
        //Перезвони
        console.log (this.state.name) // мое имя
      });

Итак, когда срабатывает обратный вызов, this.state является обновленным состоянием.
Вы можете получить измененные / обновленные данные в обратном вызове.

Поскольку setSatate является асинхронной функцией, вам нужно консольировать состояние как обратный вызов, подобный этому.

openAddBoardModal(){
    this.setState({ boardAddModalShow: true }, () => {
        console.log(this.state.boardAddModalShow)
    });
}

Ваше состояние требует некоторого времени для изменения, и, поскольку console.log (this.state.boardAddModalShow) выполняется до того, как состояние изменится, вы получите предыдущее значение в качестве вывода. Значит вам нужно записать консоль в обратном вызове в функцию setState

openAddBoardModal() {
  this.setState({ boardAddModalShow: true }, function () {
    console.log(this.state.boardAddModalShow);
  });
}

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

Согласно React docs

setState () не изменяет немедленно this.state, но создает ожидающий переход состояния. Доступ к this.state после вызова this потенциально может вернуть существующее значение. Здесь нет гарантия синхронной работы вызовов setState и вызовов может для увеличения производительности.

Зачем им setState async

Это потому, что setState изменяет состояние и вызывает повторную отрисовку. Этот может быть дорогостоящей операцией, и синхронизация может оставить браузер не отвечает.

Таким образом, вызовы setState являются асинхронными, а также группируются для лучшего Опыт и производительность пользовательского интерфейса.

setState () не всегда сразу обновляет компонент. Он может выполнить пакетное обновление или отложить его на потом. Это делает чтение this.state сразу после вызова setState () потенциальной ловушкой. Вместо этого используйте componentDidUpdate или setState callback (setState (Updater, callback)), любой из которых гарантированно сработает после применения обновления. Если вам нужно установить состояние на основе предыдущего состояния, прочтите об аргументе средства обновления ниже.

setState () всегда будет приводить к повторному рендерингу, если shouldComponentUpdate () не вернет false. Если используются изменяемые объекты и логика условного рендеринга не может быть реализована в shouldComponentUpdate (), вызов setState () только тогда, когда новое состояние отличается от предыдущего, позволит избежать ненужных повторных отрисовок .

Первый аргумент - это функция обновления с подписью:

(state, props) => stateChange

состояние - это ссылка на состояние компонента на момент применения изменения. Он не должен напрямую видоизменяться. Вместо этого изменения должны быть представлены путем создания нового объекта на основе входных данных из состояния и свойств. Например, предположим, что мы хотим увеличить значение в состоянии на props.step:

this.setState((state, props) => {
    return {counter: state.counter + props.step};
});

Да, потому что setState - асинхронная функция. Лучший способ установить состояние сразу после того, как вы напишете установленное состояние, - это использовать Object.assign следующим образом: Например, вы хотите установить для свойства isValid значение true, сделайте это так


Object.assign (this.state, {isValid: true})


Вы можете получить доступ к обновленному состоянию сразу после написания этой строки.

Приведенные выше решения не работают для хуков useState. Можно использовать приведенный ниже код

setState((prevState) => {
        console.log(boardAddModalShow)
        // call functions
        // fetch state using prevState and update
        return { ...prevState, boardAddModalShow: true }
    });

Для тех, кто пытается сделать это с помощью хуков, вам понадобится useEffect.

функция App () {
  const [x, setX] = useState (5)
  const [y, setY] = useState (15)

  console.log ("Элемент визуализирован:", x, y)

  // установка y не вызывает эффекта
  // второй аргумент - это массив зависимостей
  useEffect (() => console.log ("повторить рендеринг, потому что x изменился:", x), [x])

  function handleXClick () {
    console.log ("x перед установкой:", x)
    setX (10)
    console.log ("x в * строке * после установки:", x)
  }

  возврат <>
    
x равно {x}.
y равно {y}.
}

Вывод:

Element is rendered: 5 15
re-render because x changed: 5
(press x button)
x before setting: 5
x in *line* after setting: 5
Element is rendered: 10 15
re-render because x changed: 10
(press y button)
Element is rendered: 10 20
 this.setState({
    isMonthFee: !this.state.isMonthFee,
  }, () => {
    console.log(this.state.isMonthFee);
  })

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

Хотя useState кажется удобным подходом, состояние не устанавливается сразу, и, таким образом, ваш веб-сайт или приложение выглядят тормозными ... И если ваша страница достаточно велика, реакция займет много времени, чтобы вычислить что все должно обновляться при изменении состояния ...

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

Использование состояния для этой цели - действительно плохая идея в случае реакции.

2022 WebDevInsider