我有以下情况.我有一个父组件,其中包含一个项目列表,其中任何项目都可以在子组件中向下钻取和查看.从子组件中,您应该能够更改正在查看的项目中的值.
在React网络世界中,这将很容易解决,父级将列表存储为状态,并将项目和回调作为道具传递给子项.
使用React Native,似乎丢失了这种可能性,因为从子组件引起的更改在导航之前不会触发重新呈现.
我录制了一个视频,看起来像这样. https://gfycat.com/GreenAgitatedChanticleer
代码如下.
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,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(); },backgroundColor: '#ddd',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;
事实证明这种行为是故意的,至少现在是这样.这里有一个讨论主题:
https://github.com/facebook/react-native/issues/795
原文链接:https://www.f2er.com/react/443140.html对于寻找解决方法的任何人,我使用RCTDeviceEventEmitter在Navigator中传递数据.更新了以下代码
list.js
var React = require('react-native'); var _ = require('lodash'); var { View,ListView } = React; var Detail = require('./detail'); var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter'); var List = React.createClass({ getInitialState() { var LANGUAGES = [ { id: 1,passProps: { initialLanguage: language,l => l.id === id); clone[index].name = newName; RCTDeviceEventEmitter.emit('languageNameChanged',clone[index]); this.setState({ languages: clone,TouchableHighlight } = React; var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter'); var Detail = React.createClass({ getInitialState() { return { language: this.props.initialLanguage,subscribers: [] }; },componentDidMount() { var subscriber = RCTDeviceEventEmitter.addListener('languageNameChanged',language => { this.setState({ language }); }); this.setState({ subscribers: this.state.subscribers.concat([subscriber]) }); },componentWillUnmount() { this.state.subscribers.forEach(sub => { console.log('removing'); sub.remove(); }); },changeName() { this.props.changeName(this.state.language.id,justifyContent: 'center' }}> <Text>{this.state.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;