I have the following situation. I have a parent component that contains a list of elements, any of which can be drilled and viewed in a child component. From a child component, you should be able to change the value in the element you are looking at.
In the React world, this would be easy to solve with a parent storing the list as a state, and passing the element and callback for changes in the quality of the props for the child.
With React Native, it seems that this opportunity is lost, since making a change from a child component does not cause a re-rendering before the transition.
I recorded a video about how it looks. https://gfycat.com/GreenAgitatedChanticleer
The code is below.
index.ios.js
var React = require('react-native'); var { AppRegistry, Navigator } = React; var List = require('./list'); var listviewtest = React.createClass({ render: function() { return ( <Navigator initialRoute={{ component: List }} renderScene={(route, navigator) => { return <route.component navigator={navigator} {...route.passProps} />; }} /> ); } }); AppRegistry.registerComponent('listviewtest', () => listviewtest);
list.js
var React = require('react-native'); var _ = require('lodash'); var { View, Text, TouchableHighlight, ListView } = React; var Detail = require('./detail'); var List = React.createClass({ getInitialState() { var LANGUAGES = [ { id: 1, name: 'JavaScript' }, { id: 2, name: 'Obj-C' }, { id: 3, name: 'C#' }, { id: 4, name: 'Swift' }, { id: 5, name: 'Haskell' } ]; var ds = new ListView.DataSource({ rowHasChanged: (a, b) => a !== b }) return { languages: LANGUAGES, ds: ds.cloneWithRows(LANGUAGES) }; }, goToLanguage(language) { this.props.navigator.push({ component: Detail, passProps: { language: language, changeName: this.changeName } }); }, changeName(id, newName) { var clone = _.cloneDeep(this.state.languages); var index = _.findIndex(clone, l => l.id === id); clone[index].name = newName; this.setState({ languages: clone, ds: this.state.ds.cloneWithRows(clone) }); }, renderRow(language) { return ( <TouchableHighlight onPress={this.goToLanguage.bind(this, language)}> <View style={{ flex: 1, flexDirection: 'row', alignItems: 'center', paddingTop: 5, paddingBottom: 5, backgroundColor: '#fff', marginBottom: 1 }}> <Text style={{ marginLeft: 5, marginRight: 5 }}>{language.name}</Text> </View> </TouchableHighlight> ); }, render() { return ( <View style={{ flex: 1, backgroundColor: '#ddd' }}> <Text style={{ marginTop: 60, marginLeft: 5, marginRight: 5, marginBottom: 10 }}>Select a language</Text> <ListView dataSource={this.state.ds} renderRow={this.renderRow} /> </View> ); } }); module.exports = List;
detail.js
var React = require('react-native'); var { View, Text, TouchableHighlight } = React; var Detail = React.createClass({ changeName() { this.props.changeName(this.props.language.id, 'Language #' + Math.round(Math.random() * 1000).toString()); }, goBack() { this.props.navigator.pop(); }, render() { return ( <View style={{ flex: 1, backgroundColor: '#ddd', alignItems: 'center', justifyContent: 'center' }}> <Text>{this.props.language.name}</Text> <TouchableHighlight onPress={this.changeName}> <Text>Click to change name</Text> </TouchableHighlight> <TouchableHighlight onPress={this.goBack}> <Text>Click to go back</Text> </TouchableHighlight> </View> ); } }); module.exports = Detail;