Почему мой экран не обновляется, когда я нажимаю кнопку в первый раз, но после этого работает отлично?

Я впервые делаю автоматы с конечным состоянием. Я попытался создать программу стоп-сигнала, в которой, если вы нажмете кнопку, свет изменится один раз, начиная с зеленого, затем на желтый, если щелкнуть снова, затем на красный, прежде чем снова зациклиться. Мне удалось заставить его работать, за исключением одной маленькой ошибки. Его нужно дважды щелкнуть, прежде чем экран обновится, и я действительно не знаю, как это исправить.

Я заметил на своей консоли, что currentLightState изменяется, когда я нажимаю на него, но возвращается к предыдущему цвету при первом нажатии. Я понял, что это потому, что это не синхронизировано с моим состоянием. Однако, когда я пытаюсь поместить currentLightState внутрь класса и назначить this.state.light, currentLightState становится неопределенным. Я попытался добавить .bind(this) в конец this.state.light, но я просто получаю еще одну ошибку, говорящую, что это не функция. Какие-либо предложения?

Я не публиковал свою функцию обновления или функцию onHandleClick, поскольку она не имеет прямого отношения к currentLightState.

const lightMachine = {
  green:{
    LIGHT: 'yellow'
  },
  yellow:{
    LIGHT: 'red'
  },
  red:{
    LIGHT: 'green'
  }
}

// current location of currentLightState
let currentLightState = 'green';
class App extends React.Component{
    constructor(props){
        super(props);
        this.state = {
          light: 'green'    //initial value
        };
      }
    transition(state, action){
      // This is where my currentLightState messes up the first run 
      currentLightState = this.state.light

      const nextLightState =  lightMachine[currentLightState][action]
      this.setState({light: nextLightState}) 
    }
    render(){

        return(
            <div>
              <button onClick = {this.onHandleClick.bind(this)}>
                change the Light!
              </button>
                {currentLightState}
            </div>
            );
        }
    }

Обновлено: вот моя функция onHandleClick :)

    onHandleClick(){
      this.update(currentLightState)

    };

Кроме того, я думаю, что решил свою проблему, просто заменив currentLightState в функции рендеринга на this.state.light .

Не знаю, является ли это законным исправлением или нет, но в настоящее время оно работает.

было бы неплохо, если бы кто-то все еще мог ответить, почему, когда вы помещаете currentLightState внутри класса и назначаете ему state.light, он становится неопределенным. Это помогло бы расширить мои знания о React :)

Можете ли вы опубликовать свою функцию HandleClick? Было бы полезно все же увидеть все это.

Jake 01.05.2019 04:45

почему вы используете currentLightState в функции перехода? Почему бы просто не использовать this.state.light непосредственно в lightMaching[this.state.light][action] вот так?

Jake 01.05.2019 04:52

Основная причина, по которой я использую currentLightState, заключается в том, что, поскольку я видел другие примеры людей, использующих конечные автоматы для создания подобных программ, все они делали что-то подобное. В результате я подумал, что это правильный путь =/

Josee 01.05.2019 04:58

@Jr194! Добро пожаловать в переполнение стека! Я только что написал вам довольно подробный ответ на ваш вопрос о вашем коде и о том, почему некоторые вещи не работали.

Chris Ngo 01.05.2019 05:46
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
4
146
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Добро пожаловать на доски Jr194!

Что касается темы, я думаю, что будет полезно сохранить currentLight и lightMachine как значения, управляемые состоянием вашего компонента. Это помогает гарантировать, что вся ваша логика находится в одном контексте, избегая странных ошибок, таких как «бла-бла, не определено».

Во-вторых, вы, кажется, определили несколько функций, которые действительно можно сузить до одной. update, onHandleClick и transition, похоже, пытаются сделать одно и то же.

Наконец, рассмотрите возможность реорганизации кода в вашем lightMachine, чтобы он стал немного более интуитивным, чтобы вы могли быстро перейти к следующему свету. Вы уже знаете, какой текущий цвет в родительском ключе, действительно ли им необходимо, чтобы его объект содержал другой ключ с тем же значением?

Рассмотрим следующий код:

class App extends React.Component {
  state = {
    currentLight: "green",
    lightMachine: {
      green: {
        nextLight: "yellow"
      },
      yellow: {
        nextLight: "red"
      },
      red: {
        nextLight: "green"
      }
    }
  };

  transition = () => {
    const currentLight = this.state.currentLight;
    const nextLight = this.state.lightColors[currentLight].nextLight;
    this.setState({
      currentLight: nextLight
    });
  };
  render() {
    return (
      <div>
        <button onClick = {this.transition}>Click Me</button>
        <div>{this.state.currentLight}</div>
      </div>
    );
  }
}

Это должно позволить вам быстро менять свет, как и ожидалось. А вот и песочница: https://codesandbox.io/s/4x08ovyjp7

Дайте знать, если у вас появятся вопросы :)

Также относительно вашего вопроса о том, почему currentLightState выдает ошибку в вашем render, когда вы помещаете его в класс. Это не проблема React, это проблема JavaScript.

Давайте рассмотрим несколько примеров:

const test= "hello"
class Example extends React.Component{
   state = {
       greeting: "woof"
   }
   render(){
     <div>{test}</div>
   }
}

Как вы знаете, это не даст нам никакой ошибки. Мы подключаемся к переменной, которая определена вне нашего класса, и это совершенно нормально.

Теперь давайте посмотрим на это

class Example extends React.Component{
   state = {
       greeting: "woof"
   }

   test = this.state.greeting

   render(){
     <div>{test}</div>
   }
}

Это дает нам ошибку. Почему, потому что в вашем методе рендеринга вы обрабатываете тест как переменную, когда это не так. В объекте class, подобном тому, который вы написали, currentLightState и теперь test обрабатываются как properties, а не как переменные. Чтобы получить доступ к свойству внутри класса, вам нужно использовать ключевое слово «this», то, что вы уже делали с this.update, this.handleOnClick и т. д., которые также являются свойствами.

Теперь мы знаем, что этот код будет работать.

class Example extends React.Component{
   state = {
       greeting: "woof"
   }

   test = this.state.greeting

   render(){
     <div>{this.test}</div>
   }
}

Вау спасибо за обстоятельный ответ! Я новичок в реагирующих и конечных машинах, поэтому, честно говоря, я был очень сбит с толку после просмотра статей и примеров того, как сделать конечную машину в реакции. Посмотрев на вашу собственную версию кода, я понял, как я все усложнял. Ваш ответ немного прояснил мое замешательство :)

Josee 01.05.2019 06:57

@ Jr194, пожалуйста! Я рад, что это помогло вам :). React — настоящий зверь, и вы обязательно станете лучше, если будете использовать его больше. Если вы обнаружили, что это решение вашей проблемы, отметьте его как ответ, чтобы кто-то в будущем мог обратиться к нему, когда у него возникнет тот же вопрос.

Chris Ngo 01.05.2019 07:20

Другие вопросы по теме