Почему мой экран не обновляется, когда я нажимаю кнопку в первый раз, но впоследствии прекрасно работает?
Я впервые делаю конечные автоматы. Я попытался создать программу типа "стоп-сигнал", в которой, если вы нажмете кнопку, индикатор изменится один раз, начиная с зеленого, затем с желтого, если щелкнуть снова, а затем с красным, перед повторным циклом. Мне удалось заставить его работать, за исключением одного небольшого бага. Его нужно дважды щелкнуть перед обновлением экрана, и я не знаю, как это исправить.
Я заметил на своей консоли, что 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:)
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>
}
}