当我第一次点击我的按钮时,为什么我的屏幕没有更新,但之后工作得很好?

问题描述 投票:0回答:1

这是我第一次制作有限状态Automata。我尝试制作一个停车灯程序,如果你点击按钮,灯会改变一次,从绿色开始,然后再变为黄色,如果再次点击,再变为红色,然后再循环。我设法让它工作,除了一个小bug。在屏幕更新之前需要点击两次,我真的不知道如何修复它。

我注意到在我的控制台上,当我点击它时,currentLightState会发生变化,但在第一次点击时会恢复到之前的颜色。我发现这是因为它与我的州不同步。但是,当我尝试将currentLightState放入类中并分配this.state.light时,currentLightState变为未定义。我尝试在this.state.light的末尾添加一个.bind(this),但我只是得到另一个错误,说它不是一个函数。有什么建议?

我没有发布我的更新函数或我的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)

    };

另外,我认为我通过使用this.state.light替换render函数中的currentLightState来解决我的问题。

Idk如果这是合法的修复,但它似乎目前正在工作。

如果有人仍然可以回答为什么当你将currentLightState放入类中并为其分配state.light时,它会变得不确定。这将有助于扩展我的React知识:)

reactjs finite-state-automaton
1个回答
0
投票

欢迎来到Jr194板!

关于主题,我认为将currentLightlightMachine保持为由组件状态管理的值将是有益的。这有助于确保您的所有逻辑都在同一个上下文中,避免出现“blah blah未定义”等奇怪错误。

其次,您似乎已经定义了一些可以真正缩小到一个的函数。 update, onHandleClicktransition似乎都试图做同样的事情。

最后,考虑重新组织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>
   }
}

推荐问答