我有一个附加的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:{
},
})
答案 0 :(得分:0)
不确定这是如何工作的,但似乎答案是使用ref。我找到了rossipedia所附的例子
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;