使用Refs在React Native中调用方法没有任何作用

时间:2018-03-22 19:42:49

标签: reactjs react-native refs

我在React Native中创建了一个简单的pomodoro应用程序,我遇到了从子组件调用方法的问题。在下面的代码中,我尝试调用的方法是reset,我在父级中从resetTimer调用。这不起作用,但不会产生错误;方法中的console.logging也不会产生任何结果。我按照文档中概述的here模型进行了操作。任何解决此问题的帮助都将不胜感激!

import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';

class Timer extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            minutes: 25,
      seconds: 0,
      pomodoro: props.pomodoro,
        }
    }

  componentDidMount() {
    this.interval = setInterval(this.decrement, 1000)
  }

  reset = () => {
    this.setState(prevState => ({
      minutes: (prevState.pomodoro ? 5 : 25),
      seconds: 0,
    }))
  }

  decrement = () => {
    if ((this.state.minutes+this.state.seconds)===0){
      this.setState(prevState => ({
        pomodoro: !prevState.pomodoro,
        minutes: (prevState.pomodoro ? 25 : 5),
      }))
    } else{
      if (this.props.start){
        if (this.state.seconds===0){
          this.setState(prevState => ({
            minutes: prevState.minutes - 1,
            seconds: 59,
          }))      
        } else{
          this.setState(prevState => ({
            seconds: prevState.seconds - 1
          }))
        }
      }
    }
  }
  render() {
    return (
    <Text style={styles.time}>
      {("0"+this.state.minutes).slice(-2)}:
      {("0"+this.state.seconds).slice(-2)}
      {this.props.start}
    </Text>
    );
  }
}

export default class App extends React.Component {
  constructor (props) {
        super(props)
        this.state = {
            start: false,
      pomodoro: false,
      buttonText: "Start"
        }
  }

  toggleStart = () => this.setState(prevState => ({
    start: !prevState.start,
    buttonText: (prevState.start ? "Start" : "Stop")
  }))

  resetTimer = () => {
    this.toggleStart()
    this._timer.reset()
  }

  render() {
    return (
      <View style={styles.container}>
        <Timer 
        start={this.state.start} 
        pomodoro={this.state.pomodoro}
        reset={this.state.reset}
        toggleStart={() => this.toggleStart}
        ref={component => { this._timer = component; }}
        />
        <View style={styles.buttonRow}> 
          <Button 
          title={this.state.buttonText} 
          onPress={this.toggleStart}>
          </Button>

          <Button 
          title="Reset"
          onPress={this.resetTimer}>
          Timer.resetTime
          </Button>
        </View>
      </View>
    );
    }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  time: {
    fontSize: 70,
    color: 'tomato',
    alignItems: 'center',
    justifyContent: 'center',
  },
  buttonRow: {
    flexDirection: 'row'
  },
});

1 个答案:

答案 0 :(得分:0)

通常,您不必在父级中调用子级函数。当您发现自己处于这种情况时,可能会使组件结构过于复杂。为什么不将重置按钮移动到Timer组件?

import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';

class Timer extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            minutes: 25,
            seconds: 0,
            pomodoro: props.pomodoro,
        }
    }

    componentDidMount() {
        this.interval = setInterval(this.decrement, 1000)
    }

    reset = () => this.setState(prevState({
        minutes: (prevState.pomodoro ? 5 : 25),
        seconds: 0,
    }))

    decrement = () => {
        if ((this.state.minutes+this.state.seconds)===0){
            this.setState(prevState => ({
                pomodoro: !prevState.pomodoro,
                minutes: (prevState.pomodoro ? 25 : 5),
            }))
        } else{
            if (this.props.start){
                if (this.state.seconds===0){
                    this.setState(prevState => ({
                        minutes: prevState.minutes - 1,
                        seconds: 59,
                    }))
                } else{
                    this.setState(prevState => ({
                        seconds: prevState.seconds - 1
                    }))
                }
            }
        }
    }
    render() {
        return (
            <View>
                <Text style={styles.time}>
                    {("0"+this.state.minutes).slice(-2)}:
                    {("0"+this.state.seconds).slice(-2)}
                    {this.props.start}
                </Text>
                <View style={styles.buttonRow}>
                    <Button
                        title={this.props.buttonText}
                        onPress={this.props.toggleStart}>
                    </Button>

                    <Button
                        title="Reset"
                        onPress={this.reset}>
                        Timer.resetTime
                    </Button>
                </View>
            </View>
        );
    }
}

export default class App extends React.Component {
    constructor (props) {
        super(props)
        this.state = {
            start: false,
            pomodoro: false,
            buttonText: "Start"
        }
    }

    toggleStart = () => this.setState(prevState => ({
        start: !prevState.start,
        buttonText: (prevState.start ? "Start" : "Stop")
    }))

    render() {
        return (
            <View style={styles.container}>
                <Timer
                    start={this.state.start}
                    pomodoro={this.state.pomodoro}
                    toggleStart={this.toggleStart}
                    buttonText={this.state.buttonText}
                />
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center',
    },
    time: {
        fontSize: 70,
        color: 'tomato',
        alignItems: 'center',
        justifyContent: 'center',
    },
    buttonRow: {
        flexDirection: 'row'
    },
});