在来自孩子

时间:2018-04-24 22:13:33

标签: javascript react-native

我有一个附加的React-Native应用程序,我正在为一个类项目构建。我的START / STOP切换按钮位于父视图中,我的计时器功能位于我的子视图中。我有时间滴答,开始和停止,但我不得不每次更改时间更新孩子的父母。

我的问题是,如果我们仅在按下切换按钮时更新了父级,那会不会更好?基本上,这意味着能够从父级内部检索子级数据。我只是想不出怎么做或者甚至可能

import React from 'react';
import { Button,StyleSheet, Text, View } from 'react-native';
import ignoreWarnings from 'react-native-ignore-warnings';
ignoreWarnings(['Warning: componentWillMount is deprecated',
                'Warning: componentWillReceiveProps is deprecated'])
import PropTypes from 'prop-types'
import { Constants } from 'expo';
import { Card } from 'react-native-elements';

function merge(obj, dict){
    console.log('inside merge')
    Object.entries(dict).forEach(([k, v]) =>{
        if (!obj[k] || typeof v !== 'object')  obj[k] = v
        else  merge(obj[k], v)
    })
}

export class Timers extends React.Component{
  constructor(props){
    super(props)
    this.state={name: this.props.name,
                min:  this.props.min,
                sec:  this.props.sec,
                timer:this.props.timer,
                startFlag:this.props.startFlag,
                switchFlag:this.props.switchFlag,
                currentName:this.props.currentName,}



  }
  mountTimer(){
  //  console.log('timer mounted')
  //  this.interval=setInterval(this.inc,10000)
  //  console.log(this.interval)
  }
  clearTimer(){
  //  console.log('timer cleared')
    clearInterval(this.interval)
  }

  componentWillMount(){
  //  console.log('will mount timers')
  }

  componentDidMount(){
  //  console.log('mount1')
    dictionary=this.state
    this.props.updateParent(dictionary)
    if(this.state.name === 'WORK'){
    // console.log('work timer launched')
     this.interval=setInterval(this.inc,1000)}
  }
  static getDerivedStateFromProps(nextProps, prevState) {
    console.log('STATIC',nextProps)
    return{name: nextProps.name,
           min:  nextProps.min,
           sec:  nextProps.sec,
           timer:nextProps.timer,
           startFlag:nextProps.startFlag,
           switchFlag:nextProps.switchFlag,
           currentName:nextProps.currentName,}

    // Return null to indicate no change to state.

  }
  shouldComponentUpdate(nextProps,nextState){
    console.log('shouldCompnentUpdate')


  // if start is false  then the timer should be updating
     return this.state.timer
  }
  componentWillUnmount(){
    console.log('unmount')
    clearInterval(this.interval)
  }

  inc=()=>{
    console.log('TIC',this.state)

    if(this.state.startFlag){
      if(this.state.sec > 0){
         this.setState({sec: String(parseInt(this.state.sec - 1))},function(){
           let dictionary={left:{sec:this.state.sec}}
           this.props.updateParent(dictionary)
         })
      }else{
        this.setState({sec:'5'})
           if (this.state.min > 0){
               this.setState({min: String(parseInt(this.state.min - 1))},function(){
                 let dictionary={left:{min:this.state.min,
                                      sec:5}}
                 this.props.updateParent(dictionary)
               })
           }else{
               this.setState({min:'9',sec:'0'})
               console.log('reset123')
               this.clearTimer()
           }
      }
    }
  }


  render(){
    return(
      <View style={styles.timer}>
         <Text>{this.state.name}</Text>
         <Text>{'min: ' + this.state.min + ' sec: ' + this.state.sec }</Text>
         <Text>TBD</Text>
      </View>
    )
  }
}
export default class App extends React.Component {
  constructor(){
    super()
    this.state={left:{name:'WORK',
                      min:2,
                      sec:0,
                      timer:false,},
               right:{name:'PLAY',
                      min:2,
                      sec:0,
                      timer:false,},
               switchSide:false,
               currentName:'WORK',
               start:false,}
  }

  updateState(dictionary){
    console.log('UPDATE PARENT')

    let stateCopy={...this.state}

  /*   Object.entries(dictionary).map(([key,value])=>{
     stateCopy[key] = value.toString()
   }) */
   console.log('DICTIONARY',dictionary)
   merge(stateCopy, dictionary)

    this.setState({...stateCopy},function(){
      console.log('LEFTLEFTLEFT',this.state,'LEFTSEC')
      console.log(this.state.left.min,'LEFTMIN')
    })
    //  console.log(this.state.leftSec,'LEFTSEC')
  //  })

  }

  shouldComponentUpdate(nextProps,nextState){
  console.log('SHOULD in main app')
  return true
  }




  startToggle(){
    if(this.state.currentName === 'WORK'){
      stateCopy={...this.state}
      stateCopy.left.timer=!this.state.left.timer
      stateCopy.start=!this.state.start
      console.log('STATECOPY',stateCopy)
      this.setState({...stateCopy})






    }
    console.log('START TOGGLE START TOGGLE',this.state)
  }
  resetToggle(){
    console.log('reset')
  }
  componentWillMount(){
    console.log('will mount main APP')
  }
  render() {
    console.log('RENDER',this.state,'TIMER',this.state.left.timer)
    return (
      <View style={styles.container}>
         <Button title={this.state.start ? 'Stop' : 'Start'} onPress=
           {()=>this.startToggle()}/>
              <View style={styles.row}>
                 <Timers
                    name = {this.state.left.name}
                    min  = {this.state.left.min}
                    sec  = {this.state.left.sec}
                    timer= {this.state.left.timer}
                    startFlag  = {this.state.start}
                    switchFlag = {this.state.switchSide}
                    currentName= {this.state.currentName}
                    updateParent={(dictionary={})=>{this.updateState(dictionary)}} >
                 </Timers>
                 <Timers
                    name = {this.state.right.name}
                    min  = {this.state.right.min}
                    sec  = {this.state.right.sec}
                    timer= {this.state.right.timer}
                    startFlag  = {this.state.start}
                    switchFlag = {this.state.switchSide}
                    currentName= {this.state.currentName}
                    updateParent={(dictionary={})=>{this.updateState(dictionary)}} >
                 </Timers>
              </View>
         <Button style={styles.top} title='Reset'onPress=
           {()=>this.resetToggle()}/>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection:'column',
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  timer:{
    flex:1,
    flexDirection:'column',
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  row:{
    flex:0,
    flexDirection:'row',
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
    marginTop:55,
    marginBottom:55,
  },
  top:{
  },
})

1 个答案:

答案 0 :(得分:0)

不确定这是如何工作的,但似乎答案是使用ref。我找到了rossipedia所附的例子

&#13;
&#13;
import React, { Component } from 'react';
import { render } from 'react-dom';

class Parent extends Component {
  constructor(props) {
    super(props);
    this.child = React.createRef();
  }

  onClick = () => {
    this.child.current.getAlert();
  };

  render() {
    return (
      <div>
        <Child ref={this.child} />
        <button onClick={this.onClick}>Click</button>
      </div>
    );
  }
}

class Child extends Component {
  getAlert() {
    alert('getAlert from Child');
  }

  render() {
    return <h1>Hello</h1>;
  }
}

render(<Parent />, document.getElementById('root'));
&#13;
&#13;
&#13;