【问题标题】:How to get state value from constructor in ES6?如何从 ES6 中的构造函数获取状态值?
【发布时间】:2016-09-01 17:30:13
【问题描述】:

我正在尝试使用 ES6 语法,但尝试检索状态值时出错。

所以我的问题是:如何在 ES6 中获取状态值?以下是部分代码:

constructor(props) {
    super(props);
    this.state = {
        timeElapsed: null,
        isRunning: false
    }
}

然后当我尝试获取 isRunning 状态时,它给了我这个错误:Cannot read property 'isRunning' of undefined

if (this.state.isRunning) {

    clearInterval(this.interval);
    this.setState({
        isRunning: false
    });
    return

}

有什么想法吗?谢谢。

编辑(这里是完整的代码):

import React, {Component} from 'react';

import {
    Text,
    View,
    AppRegistry,
    StyleSheet,
    TouchableHighlight
} from 'react-native';

import Moment from 'moment';

import formatTime from 'minutes-seconds-milliseconds';

class StopWatch extends Component {

    constructor(props) {
        super(props);
        this.state = {
            timeElapsed: null,
            isRunning: false
        }
    }

    render() {
        return (
            <View style={styles.container}>
                <View style={styles.header}>
                    <View style={styles.timerWrapper}>
                        <Text style={styles.timer}>{formatTime(this.state.timeElapsed)}</Text>
                    </View>
                    <View style={styles.buttonWrapper}>
                       {this.startStopButton()}
                       {this.lapButton()}
                    </View>
                </View>
                <View style={styles.footer}>
                    <Text>List of laps</Text>
                </View>
            </View>
        )
    }

    startStopButton() {
        var style = this.state.isRunning ? styles.startButton : styles.stopButton;
        return (
            <TouchableHighlight style={[styles.button, style]} onPress={this.handleStartPress} underlayColor="gray">
                <Text>{this.state.isRunning ? 'Stop' : 'Start'}</Text>
            </TouchableHighlight>
        )
    }

    lapButton() {
        return (
            <TouchableHighlight style={[styles.button, styles.lapButton]} onPress={this.lapPress} underlayColor="gray">
                <Text>Lap</Text>
            </TouchableHighlight>
        )
    }

    border(color) {
        return {
            borderColor: color,
            borderWidth: 4
        }
    }

    handleStartPress() {
        console.log('Start was pressed');

        if (this.state.isRunning) {

            clearInterval(this.interval);
            this.setState({
                isRunning: false
            });
            return

        }

        var startTime = new Date();

        this.interval = setInterval(
            ()=>{
                this.setState({
                    timeElapsed: new Date() - startTime
                })
            }, 30
        );

        this.setState({
            isRunning: true
        })

    }

    lapPress() {
        console.log('Lap was pressed');
    }

}

var styles = StyleSheet.create({
    container: { // Main container
        flex: 1,
        alignItems: 'stretch'
    },
    header: { // Yellow
        flex: 2
    },
    footer: { // Blue
        flex: 3
    },
    timerWrapper: {
        flex: 5,
        justifyContent: 'center',
        alignItems: 'center'
    },
    timer: {
        fontSize: 60
    },
    buttonWrapper: {
        flex: 3,
        flexDirection: 'row',
        justifyContent: 'space-around',
        alignItems: 'center'
    },
    button: {
        borderWidth: 2,
        height: 100,
        width: 100,
        borderRadius: 50,
        justifyContent: 'center',
        alignItems: 'center'
    },
    startButton: {
        borderColor: 'red'
    },
    stopButton: {
        borderColor: 'green'
    },
    lapButton: {
        borderColor: 'blue'
    }
});

// AppRegistry.registerComponent('stopWatch', function() {
//     return StopWatch;
// });

AppRegistry.registerComponent('stopwatch', () => StopWatch);

编辑 2:

这是一个在构造函数中有和没有绑定的组合解决方案:

import React, {Component} from 'react';

import {
    Text,
    View,
    AppRegistry,
    StyleSheet,
    TouchableHighlight
} from 'react-native';

import Moment from 'moment';

import formatTime from 'minutes-seconds-milliseconds';

class StopWatch extends Component {

    constructor(props) {
        super(props);

        this.state = {
            timeElapsed: null,
            isRunning: false
        }

        this.startStopButton = this.startStopButton.bind(this)
        this.lapButton = this.lapButton.bind(this)
    }

    render() {
        return (
            <View style={styles.container}>
                <View style={styles.header}>
                    <View style={styles.timerWrapper}>
                        <Text style={styles.timer}>{formatTime(this.state.timeElapsed)}</Text>
                    </View>
                    <View style={styles.buttonWrapper}>
                       {this.startStopButton()}
                       {this.lapButton()}
                    </View>
                </View>
                <View style={styles.footer}>
                    <Text>List of laps</Text>
                </View>
            </View>
        )
    }

    startStopButton() {

        var style = this.state.isRunning ? styles.startButton : styles.stopButton;

        handleStartPress = () => {
            console.log('Start was pressed');

            if (this.state.isRunning) {

                clearInterval(this.interval);
                this.setState({
                    isRunning: false
                });
                return

            }

            var startTime = new Date();

            this.interval = setInterval(
                ()=>{
                    this.setState({
                        timeElapsed: new Date() - startTime
                    })
                }, 30
            );

            this.setState({
                isRunning: true
            })
        }

        return (
            <TouchableHighlight style={[styles.button, style]} onPress={handleStartPress} underlayColor="gray">
                <Text>{this.state.isRunning ? 'Stop' : 'Start'}</Text>
            </TouchableHighlight>
        )

    }

    lapButton() {

        handleLapPress = () => {
            console.log('Lap was pressed');
        }

        return (
            <TouchableHighlight style={[styles.button, styles.lapButton]} onPress={handleLapPress} underlayColor="gray">
                <Text>Lap</Text>
            </TouchableHighlight>
        )

    }

    border(color) {

        return {
            borderColor: color,
            borderWidth: 4
        }

    }

}

var styles = StyleSheet.create({
    container: { // Main container
        flex: 1,
        alignItems: 'stretch'
    },
    header: { // Yellow
        flex: 2
    },
    footer: { // Blue
        flex: 3
    },
    timerWrapper: {
        flex: 5,
        justifyContent: 'center',
        alignItems: 'center'
    },
    timer: {
        fontSize: 60
    },
    buttonWrapper: {
        flex: 3,
        flexDirection: 'row',
        justifyContent: 'space-around',
        alignItems: 'center'
    },
    button: {
        borderWidth: 2,
        height: 100,
        width: 100,
        borderRadius: 50,
        justifyContent: 'center',
        alignItems: 'center'
    },
    startButton: {
        borderColor: 'red'
    },
    stopButton: {
        borderColor: 'green'
    },
    lapButton: {
        borderColor: 'blue'
    }
});

AppRegistry.registerComponent('stopwatch', () => StopWatch);

【问题讨论】:

  • 您的第二个 sn-p - 是在 render 类方法中吗?还是在另一个类方法中?如果是另一个类方法,请确保它正确绑定到this
  • 向我们展示你的函数,也许你的this 不见了,你使用箭头函数吗?
  • 我已经添加了完整的代码。
  • 你将handleStartPress作为回调传递,你必须将bind handleStartPress函数传递给你当前的this,使用箭头函数语法handleStartPress = () =&gt; {//code}
  • 在我看来,让 handleStartPress 方法在外面并从构造函数中绑定它更可取

标签: reactjs react-native ecmascript-6


【解决方案1】:

您需要将您的类方法绑定到正确的this。有关使用 ES6 类的信息,请参阅 facebook 文档:https://facebook.github.io/react/docs/reusable-components.html#es6-classes

要修复您的错误,请将您的方法绑定到您的类构造函数中:

class StopWatch extends Component {

constructor(props) {
    super(props);

    this.state = {
        timeElapsed: null,
        isRunning: false
    }

    this.startStopButton= this.startStopButton.bind(this)
    this.lapButton = this.lapButton.bind(this)
    this.handleStartPress = this.handleStartPress.bind(this)
    this.handleLap = this.handleLap.bind(this)
}

render() {
    return (
        <View style={styles.container}>
            <View style={styles.header}>
                <View style={styles.timerWrapper}>
                    <Text style={styles.timer}>{formatTime(this.state.timeElapsed)}</Text>
                </View>
                <View style={styles.buttonWrapper}>
                   {this.startStopButton()}
                   {this.lapButton()}
                </View>
            </View>
            <View style={styles.footer}>
                <Text>List of laps</Text>
            </View>
        </View>
    )
}

startStopButton() {
    var style = this.state.isRunning ? styles.startButton : styles.stopButton;
    return (
        <TouchableHighlight style={[styles.button, style]} onPress={this.handleStartPress} underlayColor="gray">
            <Text>{this.state.isRunning ? 'Stop' : 'Start'}</Text>
        </TouchableHighlight>
    )
}

lapButton() {
    return (
        <TouchableHighlight style={[styles.button, styles.lapButton]} onPress={this.lapPress} underlayColor="gray">
            <Text>Lap</Text>
        </TouchableHighlight>
    )
}

border(color) {
    return {
        borderColor: color,
        borderWidth: 4
    }
}

handleStartPress() {
    console.log('Start was pressed');

    if (this.state.isRunning) {

        clearInterval(this.interval);
        this.setState({
            isRunning: false
        });
        return

    }

    var startTime = new Date();

    this.interval = setInterval(
        ()=>{
            this.setState({
                timeElapsed: new Date() - startTime
            })
        }, 30
    );

    this.setState({
        isRunning: true
    })

}

lapPress() {
    console.log('Lap was pressed');
}

}

抱歉,格式错误

【讨论】:

  • 你摇滚,我只能这么说。 :)
  • 这对我不起作用,对其他人有用吗?
【解决方案2】:

这与 ES6 无关,这是 Javascript 工作方式的固有困难。

你的错误在这里:

onPress={this.lapPress}

您认为这意味着“按下按钮时,在我的组件上调用方法 lapPress”。它没有。这意味着“当按下按钮时,从我的组件调用方法 lapPress,使用 this 碰巧设置的任何值”。

有几种方法可以正确地将 this 绑定到它的方法,但最简单的(在 ES6 中)可能是

onPress={() => this.lapPress()}

【讨论】:

  • 这不是最好的方法,在每个render 上创建一个新的function,更好的方法是将回调传递给箭头函数
  • "程序员浪费大量时间去思考或担心他们程序中非关键部分的速度,而在考虑调试和维护时,这些效率上的尝试实际上产生了强烈的负面影响。我们应该忘记小的效率,比如大约 97% 的时间。” ——唐纳德·克努斯
猜你喜欢
  • 2016-05-11
  • 2017-04-07
  • 1970-01-01
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-19
相关资源
最近更新 更多