简体   繁体   English

React-native是否不应该仅渲染类似于React工作方式的更改组件?

[英]Shouldn't React-native render only changed components similar to how React works?

I am new to the React scene but I am fairly familiar with its structure and at the very least how to make simple webapps using it but this got me scratching my head for hours 我是React领域的新手,但我对它的结构以及至少如何使用它来制作简单的Webapp相当熟悉,但这使我抓了好几个小时

I am making a Tic Tac Toe using React-native, I currently experiment only on Android. 我正在使用React-native制作井字游戏,目前仅在Android上进行实验。 These are the parts from my code that I think explains my situation 这些是我代码中的部分,我认为这可以解释我的情况

import Tile from "./Tile"

export default class Playground extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            board: [["?", "?", "?"], ["?", "?", "?"], ["?", "?", "?"]],
            turn: "X"
        }
    }

    move(x, y) {
        if (this.state.board[x][y] == "?") {
            var currentTurn = this.state.turn
            var currentBoard = this.state.board
            currentBoard[x][y] = this.state.turn
            this.setState({board: currentBoard});
            //this.isGameOver(x, y);
        }
    }

    isGameOver(x, y) {
        //Game Over Test
    }

    render() {
        return (
            <View style={styles.container}>
                <View style={styles.row}>
                    <Tile onPress={this.move.bind(this, 0, 0)} icon={this.state.board[0][0]}/>
                    <Tile onPress={this.move.bind(this, 0, 1)} icon={this.state.board[0][1]}/>
                    <Tile onPress={this.move.bind(this, 0, 2)} icon={this.state.board[0][2]}/>
                </View>
                <View style={styles.row}>
                    <Tile onPress={this.move.bind(this, 1, 0)} icon={this.state.board[1][0]}/>
                    <Tile onPress={this.move.bind(this, 1, 1)} icon={this.state.board[1][1]}/>
                    <Tile onPress={this.move.bind(this, 1, 2)} icon={this.state.board[1][2]}/>
                </View>
                <View style={styles.row}>
                    <Tile onPress={this.move.bind(this, 2, 0)} icon={this.state.board[2][0]}/>
                    <Tile onPress={this.move.bind(this, 2, 1)} icon={this.state.board[2][1]}/>
                    <Tile onPress={this.move.bind(this, 2, 2)} icon={this.state.board[2][2]}/>
                </View>
            </View>
        )
    }
}

And of course the code for the tiles 当然还有磁贴的代码

export default class Tile extends React.Component {
    constructor(props) {
        super(props)
    }

    rand() {
        return Math.random() * 256;
    }

    randColor() {
        return "rgb(" + this.rand() + " ," + this.rand() + " ," + this.rand() + ")";
    }

    determineIcon() {
        if (this.props.icon == "X") {
            return (<Text>O</Text>)
        } else if (this.props.icon == "O") {
            return (<Text>X</Text>)
        } else {
            return null;
        }
    }

    render() {
        console.log("Things are happening!")
        return (
            <TouchableHighlight onPress={this.props.onPress} underlayColor={this.randColor()}>
                <View style={[styles.square, {backgroundColor: this.randColor()}]}>
                    {this.determineIcon()}
                </View>
            </TouchableHighlight>
        )
    }
}

So what I noticed at first was that every time I clicked on a tile and it was successfully changed to an X ALL colours were regenerated again which made me realise that my app is re-rendering everything. 因此,我最初注意到的是,每次我单击图块并将其成功更改为X时,所有颜色都会重新生成,这使我意识到我的应用程序正在重新渲染所有内容。

So I thought it was the fault of that random function and decided to have all squares be orange, but I wanted to know whether it was still re-rendering everything or just the tile I pressed, so I put that console log to see how many times is the rendering happening and to my dismay it happened 9 times. 因此,我认为这是该随机函数的错误,因此决定将所有正方形都设为橙色,但是我想知道它是仍在重新渲染所有内容还是仅渲染了我按下的图块,因此我将控制台日志放入其中以查看有多少个渲染正在发生很多次,令我沮丧的是它发生了9次。

I ended up removing the the onPress and icon properties from the 8 last tiles and turning them into completely static objects and changing board into a simple Boolean that I passed to the first tile. 我最终从最后8个图块中删除了onPress和icon属性,并将它们变成完全静态的对象,并将板子更改为一个简单的布尔值,然后将其传递给第一个图块。 But no, it still rendered all 9 elements, again! 但是不,它仍然呈现了所有9个元素!

Can someone please explain to me, Shouldn't React-native render only changed components similar to how React works? 有人可以告诉我,React-native不应该只渲染与React相似的组件吗?

Recently I've learned that when a new state is being set (or when props are changed), all your components in the hierarchy for this parent component will trigger the render function. 最近,我了解到,当设置新状态(或更改道具)时,此父组件的层次结构中的所有组件都会触发render函数。 This is true for React and not specific to React-Native ; 这对于React是正确的,而不是特定于React-Native it happens because React's shouldComponentUpdate() defaults to true . 这是因为React的shouldComponentUpdate()默认为true

This doesn't mean that the components are actually getting re-rendered again . 这并不意味着实际上要重新渲染组件 React is smart enough to figure out if it needs to update the UI or not as part of a process called "Reconciliation". React足够聪明,可以确定是否需要更新UI,这是称为“对帐”的过程的一部分。

That said, if you have lots of components with a deep hierarchy, this behavior might put some stress on the JS thread. 也就是说,如果您有许多具有深层次结构的组件,则此行为可能会给JS线程带来一些压力。 If you run into performance issues you can override shouldComponentUpdate to do your own logic, or just inherit from React.PureComponent instead of React.Component as it says in the docs : 如果遇到性能问题,您可以重写shouldComponentUpdate来执行自己的逻辑,或者仅继承React.PureComponent而不是docs中所说的React.Component

If you determine a specific component is slow after profiling, you may change it to inherit from React.PureComponent which implements shouldComponentUpdate() with a shallow prop and state comparison. 如果您确定某个特定组件在分析后运行缓慢,则可以将其更改为从React.PureComponent继承,该组件通过浅层支持和状态比较来实现shouldComponentUpdate()。 If you are confident you want to write it by hand, you may compare this.props with nextProps and this.state with nextState and return false to tell React the update can be skipped. 如果您确定要手工编写,可以将this.props与nextProps进行比较,并将this.state与nextState进行比较,然后返回false来告诉React可以跳过更新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM