【问题标题】:Why does my screen not update when I click my button the first time, but works perfectly fine afterwards?为什么我第一次单击按钮时屏幕没有更新,但之后却可以正常工作?
【发布时间】:2019-05-01 02:29:36
【问题描述】:

这是我第一次制作有限状态自动机。我尝试制作一个停止灯类型的程序,如果您单击按钮,灯会改变一次,从绿色开始,如果再次单击则变为黄色,然后变为红色,然后再次循环。我设法使它工作,除了一个小错误。屏幕更新之前需要点击两次,我真的不知道如何修复它。

我在控制台上注意到,当我单击它时 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 替换渲染函数中的 currentLightState 即可解决我的问题。

Idk 如果这是否是合法的修复,但它目前似乎有效。

如果有人仍然可以回答为什么当您将 currentLightState 放入类中并将 state.light 分配给它时,它会变得未定义,那就太好了。这将有助于扩展我的 React 知识:)

【问题讨论】:

  • 你能发布你的 onHandleClick 函数吗?看到这一切仍然很有用。
  • 为什么在过渡函数中使用 currentLightState?为什么不直接在 lightMacing[this.state.light][action] 中直接使用 this.state.light 呢?
  • 我在那里使用 currentLightState 的主要原因是因为当我看到人们使用有限状态机来制作这样的程序的其他示例时,他们都做了类似的事情。结果我认为这是正确的方法=/
  • @Jr194!欢迎来到堆栈溢出!我刚刚就您的代码以及为什么有些事情不起作用的问题给您写了一个非常详尽的答案。

标签: reactjs finite-state-automaton


【解决方案1】:

欢迎来到 Jr194 董事会!

关于主题,我认为将currentLightlightMachine 保留为由组件状态管理的值会很有好处。这有助于确保您的所有逻辑都在同一个上下文中,避免出现“blah blah is not defined”之类的奇怪错误。

其次,您似乎已经定义了一些真正可以缩小到一个的函数。 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>
   }
}

【讨论】:

  • 哇,感谢您的详尽回答!我对反应和有限机器还是很陌生,所以在查找有关如何在反应中制造有限机器的文章和示例后,我真的很困惑。在查看了您自己的代码版本后,我意识到我是多么地把事情复杂化了。你的回答解决了我的很多困惑:)
  • @Jr194 不客气!我很高兴这对您有所帮助:)。 React 是一个绝对的野兽,当你更多地使用它时,你肯定会变得更好。如果您发现这可以解决您的问题,请将其标记为答案,以便将来有人遇到相同问题时可以参考。
猜你喜欢
  • 2011-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 2017-08-19
  • 2011-09-18
  • 2021-05-14
  • 1970-01-01
相关资源
最近更新 更多