问题
React Native newbie here.
I'm trying to build a simple React Native app for practice that is essentially just a multi-page contact form.
I'm having trouble figuring out the best way to pass props / state to my child components when I'm rendering them via the navigator (navigatorRenderScene function)
Whenever I try to assign props to my component here, it allows me to pass a string but not a function or an object. For example in the component First, I'm trying to pass a string and a function. Only the string will hold its value once the page is rendered.
Am I doing this completely the wrong way? Do I need to look into some kind of state management system like Flux or Redux? Maybe even the redux router package? (Haven't even touched these yet to be honest)
The routing is all working great, it's just the props / state that I can't figure out.
Here's my index
import React, { Component } from 'react';
import {
AppRegistry,
Navigator,
StyleSheet,
Text,
View,
TouchableHighlight
} from 'react-native';
import { Container, Header, Title, Content, List, ListItem, InputGroup, Input, Button, Icon, Picker } from 'native-base'
// a bunch of crap here being imported that I don't need, I'll trim it down later.
import First from './components/First'
import Second from './components/Second'
class App extends Component {
constructor(props) {
super(props);
this.state = {
text : 'initial state',
sentBy : '',
company : '',
phoneNumber : ''
};
this.testFunc = this.testFunc.bind(this)
}
// end constructor
mostRecentPush() {
// firebase stuff, not really important to the problem
console.log('pushing input data to DB')
firebase.database().ref('mostRecent/').set({
'body' : this.state.text,
'sentBy' : this.state.sentBy,
'location' : this.state.pickerValue,
'company' : this.state.company
});
firebase.database().ref('emails/').push({
'body' : this.state.text,
'sentBy' : this.state.sentBy,
'location' : this.state.pickerValue,
'company' : this.state.company
})
}
// end mostRecentPush() / firebase stuff
onButtonPress() {
this.props.navigator.push({
id: 'Second'
})
} // end onButtonPress
testFunc() {
console.log('calling this from the index')
}
render() {
console.log('rendering home')
return (
<Navigator
initialRoute = {{
id: 'First'
}}
renderScene={
this.navigatorRenderScene
}
/>
)
} // end render
navigatorRenderScene(route, navigator) {
_navigator = navigator;
switch (route.id){
case 'First':
return(<First testString="cat123" testFunc={this.testFunc} navigator={navigator} title="First" />)
// passing our navigator value as props so that the component has access to it
case 'Second':
return(<Second navigator={navigator} title="Second" />)
case 'Third':
return(<Third navigator={navigator} title="Third" />)
case 'Fourth':
return(<Fourth navigator={navigator} title="Fourth" />)
case 'Fifth':
return(<Fifth navigator={navigator} title="Fifth" />)
} //end switch
} // end navigatorRenderScene
} // end component
AppRegistry.registerComponent('App', () => App);
And here's an example component, First
import React, { Component } from 'react';
import {
AppRegistry,
Navigator,
StyleSheet,
Text,
View,
TouchableHighlight
} from 'react-native';
import { Container, Header, Title, Content, List, ListItem, InputGroup, Input, Button, Icon, Picker } from 'native-base'
// too much stuff being imported, will clean this up later
class First extends Component {
constructor(props) {
super(props)
this.onButtonPress = this.onButtonPress.bind(this)
}
onButtonPress() {
this.setState({
text: 'changed state from first component'
})
console.log(this.state)
this.props.navigator.push({
id: 'Second'
})
}
render() {
return(
<Container>
{console.log('rendering first')}
<Content>
<List>
<ListItem>
<InputGroup>
<Input
placeholder='Name'
/>
</InputGroup>
</ListItem>
</List>
<TouchableHighlight onPress={this.onButtonPress}>
<Text>Go to Page 2</Text>
</TouchableHighlight>
</Content>
</Container>
)
}
}
export default First
回答1:
I think the the problem it's with the scope. When setting the renderScene prop to the navigator, you are not binding that function to the actual class, therefore when the navigatorRenderScene
gets executed, the scope it's not the same as testFunc
.
Try changing this line of code:
navigatorRenderScene(route, navigator) {
//...
}
For this:
navigatorRenderScene = (route, navigator) => {
// ...
}
The arrow function will bind the navigatorRenderScene
to the class, therefore this.testFunc
will exist there.
Other options to do the binding
If you don't want to use an arrow function, you could try something like this in the constructor
.
// First options
this.navigatorRenderScene = this.navigatorRenderScene.bind(this)
Or you can also use the bind
method directly on the callback
// Second option
renderScene={
this.navigatorRenderScene.bind(this)
}
Or an arrow function as well
// Third option
renderScene={
(route, navigator) => this.navigatorRenderScene(route, navigator)
}
Let me know if this works. Good luck!
来源:https://stackoverflow.com/questions/40034617/passing-props-state-in-react-native-navigator