不应该React-native渲染只改变组件类似于React的工作原理吗?

时间:2017-03-26 20:33:48

标签: javascript android reactjs react-native

我是React场景的新手,但我对它的结构非常熟悉,至少如何使用它制作简单的webapps但是这让我头疼了好几个小时

我正在使用React-native制作Tic Tac Toe,我目前只在Android上进行实验。这些是我的代码中的部分,我认为这解释了我的情况

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>
        )
    }
}

当然还有瓷砖的代码

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>
        )
    }
}

所以我最初注意到的是每次我点击一个瓷砖并且它已成功更改为X所有颜色再次重新生成,这让我意识到我的应用程序正在重新渲染所有内容。

所以我认为这是随机函数的错误,并决定将所有正方形都设为橙色,但我想知道它是否仍在重新渲染所有内容或只是我按下的磁贴,所以我把控制台日志放到看看渲染发生了多少次,令我沮丧的是它发生了9次。

我最终删除了最后8个图块中的onPress和图标属性,并将它们转换为完全静态的对象,并将板更改为我传递给第一个图块的简单布尔值。但不,它仍然再次呈现所有9个元素!

有人可以向我解释一下,React-native渲染不应该只更改与React工作方式相似的组件吗?

1 个答案:

答案 0 :(得分:4)

最近我了解到,当设置新状态时(或更改道具时),此父组件层次结构中的所有组件都将触发render功能。这适用于React,而不是React-Native特有的;这是因为React的shouldComponentUpdate()默认为true

这并不意味着组件实际上会再次重新渲染。 React非常聪明,可以确定是否需要更新UI,这是一个名为&#34; Reconciliation&#34;的过程的一部分。

也就是说,如果你有很多具有深层次结构的组件,这种行为可能会给JS线程带来一些压力。如果您遇到性能问题,可以覆盖shouldComponentUpdate来执行自己的逻辑,或者只是继承React.PureComponent而不是React.Component,如docs中所述:

  

如果您在分析后确定特定组件的速度很慢,则可以   将其更改为从实现的React.PureComponent继承   shouldComponentUpdate()具有浅的prop和状态比较。如果   你有信心想要手工编写,你可以比较   this.props with nextProps和this.state with nextState并返回   false告诉React可以跳过更新。