javascript - 为什么 React 在提升状态时运行缓慢?

标签 javascript reactjs

我正在制作一款游戏,其中一个人制作一个迷宫,然后将该迷宫导出到数据库供其他人尝试。我正在制作一个非常大的网格 (800 x 800) 并将方 block onMouseOver 变成黑色以指示迷宫的墙壁。有一段时间,它似乎运行良好,但在某个时候,它开始滞后于 onMouseOver,有点杀死游戏。我不确定是否可以让 div 改变颜色的速度足够快以实现此功能。

它似乎工作正常,直到我将 Square 组件的 id 移动到 Maze 组件的状态以准备将其发送到后端。

这是代码和框:https://codesandbox.io/s/github/reedmacdonald/mazeProject


class Maze extends Component{
    constructor(props){
        super();
        this.state = {
            buttonClicked:'',
            buildShowing: 'inline',
            testShowing: 'none',
            testing: false,
            clicked: true,
            finishShowing:'inline',
            submitShowing:'none',
            maze:[],
            name:''

        }
    }


    changeToRed = () => {
        this.setState({
            submitShowing:'inline',
            finishShowing: 'none',
            buttonClicked:'red',
            testing: true})
    }



    nameThisMaze = (e) => {
        e.preventDefault()
        var nameValue = document.getElementById("uniqueID").value
        this.setState({
            name: nameValue
        })
        alert(`name is now ${this.state.name}`)
    }

    handleSubmit = async (e) => {
        e.preventDefault();
        const mazeResponse = await fetch('/maze', {
            method: 'POST',
            credentials: 'include',
            body: JSON.stringify(this.state),
            headers:{
                "Content-type" : 'application/json'
            }
        })
        const parsedResponse = await mazeResponse.json();
        console.log(parsedResponse)
    }

    pushValueUp = (brick) => {
        this.state.maze.push(brick)
        this.setState({
            maze:this.state.maze
        })
    }



    render(){
        const arrayOne= new Array(6400).fill('hello')

        const theMaze = arrayOne.map((movie, i) => {
            return (
                <Square pushValueUp = {this.pushValueUp} scar={i} clicked =
                {this.state.clicked} key={i} name="brick" button=
                {this.state.buttonClicked} color={this.state.colorToChangeMaze}
            className= 'cell'/>
        )
        })
        return (
            <div onDoubleClick={this.changeToClicked}>
            <div onMouseOver={(this.state.testing) ?
            this.outOfBounds:undefined} className="outOfBounds"></div>
            <div onMouseOver={(this.state.testing) ?
            this.outOfBounds:undefined} className="outOfBoundsTwo"></div>
            <div onMouseOver={(this.state.testing) ?
            this.outOfBounds:undefined} className="outOfBoundsThree"></div>
            <form onSubmit={this.handleSubmit}>
            <button type="button" onClick={this.changeButtons}
        className="finishMaze" style=
            {{'display':this.state.finishShowing}}>Finish Maze</button>
        <button type="submit" className="finishMaze"
        style=``{{'display':this.state.submitShowing}}>Submit Maze</button>

        <div className="grid">
            {theMaze}
            </div>
            </form>

            <button className="startEndButton" onClick={this.changeToRed} style={{'display':this.state.testShowing}}>Test Maze</button>
        <button className="startEndButton" onClick={this.changeToBlack} style={{'display':this.state.buildShowing}}>Build Maze</button>

        <form className="nameForm" onSubmit={this.nameThisMaze}>
            <input id = "uniqueID" name = "mazeName" className="giveName" type="text" placeholder=" Name of Your maze"></input>
            <button type="submit"> Give name</button>
        </form>
        </div>
    )}
}

class Square extends Component{
    constructor(props) {
        super(props);
        this.state = {
            scar: this.props.scar,
            color: 'white',
            colorToChange:null,
            changeColor: false,
            clicked:this.props.clicked
        };
    }


    darnThis = () =>{
        this.props.pushValueUp(this.props.scar)
    }
    switchColor =()=>{
        (this.state.colorToChange==='black' && this.props.button=== 'red')&& this.hitWall()
        this.darnThis()
        this.setState({
            changeColor:true,
            colorToChange:this.props.button})
    }
    render(){
        return(
            <div className="boxes" onMouseOver = {this.switchColor} style={{'height':'5px','width':'5px','backgroundColor':this.state.changeColor ? this.state.colorToChange : this.state.color,'margin':'0'}}>
    </div>
    )
    }
}

很抱歉我在那里放了这么多代码(我拿出了很多代码,以防你对事情的去向感到困惑),我只是不知道为什么onMouseOver太落后了。

最佳答案

我发现并解决了一些问题。

  1. 不需要每次都创建 6400 大小的数组,因为您只需要迭代 6400 次。只需在组件外部创建一次并通过范围查找使用它即可。
  2. maze 未在任何地方用于渲染。因此,您可以将其保留在 Maze 实例上,如 this.maze。调用 setState 将不必要地重新触发整个 React 生命周期。
  3. 您始终在 onMouseOver 处理程序中调用 switchColor。当与父级中的 setState 结合使用时,这是相当昂贵的。特别是因为该事件经常被触发。因此,我将对父级的调用移至 componentDidUpdate 中,并根据调用的父级编写一些条件 (prevState.colorToChange !== this.state.colorToChange)。您应该更改此条件以满足您的需要。

Codesandbox 是 here 。这些只是我能想到的一些优化,该应用程序似乎 react 良好。另请记住,您不应该 modify state directly .

我在每个方 block 上使用 refs 进行了实验。我没有时间做一个完整的例子,但想法就在那里。 link .

关于javascript - 为什么 React 在提升状态时运行缓慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56096295/

相关文章:

javascript - 如何在 jQuery 中使用 if 语句

javascript - React - 将唯一键添加到数组映射

javascript - .NET Core 查看页面的值到 JavaScript 数组

javascript - 无法居中图像

javascript - 如何在 jQuery UI 中将多个可排序列表相互连接?

javascript - 根据触发器 anchor 的文本在 Jquery UI 对话框中创建动态按钮名称

javascript - Netlify 正在显示我的 Gatsby 网站的 html 版本

javascript - 根据字符串数组过滤对象数组

node.js - fs.writeFile 在我的 ReactJs/NodeJs 应用程序上不起作用

javascript - 在子组件中传递和调用的函数无权访问父状态值