运行 来自子组件的父组件中的功能 - React Navigator 屏幕 w/o redux
Run function in parent component from child - React Navigator screen w/o redux
我正在使用 react-native-i18n、react-native-popup-menu、react-navigation + expo(但我想尽快弹出)。当用户可以 select 语言(自动检测或强制:英语、德语等)和一两个其他设置时,我想创建设置屏幕。
我正在尝试使用 AsyncStorage 来存储用户的首选项。
当用户更改设置应用程序时,我想在 AsyncStorage 和 App.js 中的状态对象中设置数据(如果需要刷新主 component/full 应用程序)。但是我在使用道具时遇到了问题。
App.js片段:
const navOpt = ({ navigation }) => ({
headerStyle: { backgroundColor: 'blue', elevation: null },
headerRight: (<Menu>
<MenuTrigger><MyIcon name="more" /></MenuTrigger>
<MenuOptions>
<MenuOption onSelect={() => navigation.navigate('Settings')} text='Settings' />
</MenuOptions>
</Menu>),
});
const RootNav = StackNavigator({
Home: { screen: HomeScreen },
Settings: { screen: SettingsScreen }
}, {
navigationOptions: navOpt
});
export default class App extends Component {
constructor(props) {
super(props);
this.langHandler = this.langHandler.bind(this);
this.state = {
isLoadingComplete: false,
currentLang: '',
selectedLang: null,
selectedTheme: null
};
}
async componentWillMount() {
try {
AsyncStorage.multiGet(['lang', 'theme'], (err, stores) => {
this.setState({ selectedLang: stores[0].lang });
this.setState({ selectedTheme: stores[0].theme });
});
} catch (e) {
console.log(e);
return;
}
try {
await I18n.initAsync();
} catch (e) {
console.log(e);
return;
}
console.log(this.state.selectedLang);
if (this.state.selectedLang != null && this.state.selectedLang !== '') {
this.setState({ currentLang: this.state.selectedLang });
} else {
this.setState({ currentLang: I18n.locale });
}
this.setState({ isLoadingComplete: true });
console.log(this.state);
}
langHandler(lang) {
console.log(`xx${lang}`);
this.setState({
isLoadingComplete: false
});
}
render() {
if (this.state.isLoadingComplete) return (<MenuProvider><RootNav /></MenuProvider>);
return <View />;
}
}
SettingsScreen.js - 这是最简单的版本:
import React, { Component } from 'react';
import { StyleSheet, View, Button, TextInput, AsyncStorage } from 'react-native';
class SettingsScreen extends Component {
static navigationOptions = {
title: 'Settings',
};
constructor(props) {
super(props);
this.state = {
text: ''
};
}
saveData() {
AsyncStorage.setItem('lang', this.state.text);
this.props.langHandler(this.state.text);
}
render() {
return (
<View style={styles.container}>
<View>
<TextInput onChangeText={(text) => this.setState({ text })} />
<Button title='set' onPress={() => this.saveData()} />
</View>
</View>
);
}
}
我正在尝试设置
const RootNav = StackNavigator({
Home: { screen: HomeScreen },
Settings: { screen: props => <SettingsScreen (...props) />}
但是不起作用。
也许我需要使用 Redux?但如果有可能避免这种情况更好:)
也许我应该以不同的方式做所有事情?
感谢您的宝贵时间。
最好的问候
您要找的是screenProps
。您必须将 langHandler
添加到 RootNav
screenProps。
render() {
const screenProps = {
langHandler: this.langHandler,
};
if (this.state.isLoadingComplete) {
return (
<MenuProvider>
<RootNav screenProps={screenProps} />
</MenuProvider>);
}
return <View />;
}
然后您就可以在 SettingsScreen
中使用 this.props.screenProps.langHandler
访问 langHandler
saveData() {
AsyncStorage.setItem('lang', this.state.text);
this.props.screenProps.langHandler(this.state.text);
}
我正在使用 react-native-i18n、react-native-popup-menu、react-navigation + expo(但我想尽快弹出)。当用户可以 select 语言(自动检测或强制:英语、德语等)和一两个其他设置时,我想创建设置屏幕。
我正在尝试使用 AsyncStorage 来存储用户的首选项。 当用户更改设置应用程序时,我想在 AsyncStorage 和 App.js 中的状态对象中设置数据(如果需要刷新主 component/full 应用程序)。但是我在使用道具时遇到了问题。
App.js片段:
const navOpt = ({ navigation }) => ({
headerStyle: { backgroundColor: 'blue', elevation: null },
headerRight: (<Menu>
<MenuTrigger><MyIcon name="more" /></MenuTrigger>
<MenuOptions>
<MenuOption onSelect={() => navigation.navigate('Settings')} text='Settings' />
</MenuOptions>
</Menu>),
});
const RootNav = StackNavigator({
Home: { screen: HomeScreen },
Settings: { screen: SettingsScreen }
}, {
navigationOptions: navOpt
});
export default class App extends Component {
constructor(props) {
super(props);
this.langHandler = this.langHandler.bind(this);
this.state = {
isLoadingComplete: false,
currentLang: '',
selectedLang: null,
selectedTheme: null
};
}
async componentWillMount() {
try {
AsyncStorage.multiGet(['lang', 'theme'], (err, stores) => {
this.setState({ selectedLang: stores[0].lang });
this.setState({ selectedTheme: stores[0].theme });
});
} catch (e) {
console.log(e);
return;
}
try {
await I18n.initAsync();
} catch (e) {
console.log(e);
return;
}
console.log(this.state.selectedLang);
if (this.state.selectedLang != null && this.state.selectedLang !== '') {
this.setState({ currentLang: this.state.selectedLang });
} else {
this.setState({ currentLang: I18n.locale });
}
this.setState({ isLoadingComplete: true });
console.log(this.state);
}
langHandler(lang) {
console.log(`xx${lang}`);
this.setState({
isLoadingComplete: false
});
}
render() {
if (this.state.isLoadingComplete) return (<MenuProvider><RootNav /></MenuProvider>);
return <View />;
}
}
SettingsScreen.js - 这是最简单的版本:
import React, { Component } from 'react';
import { StyleSheet, View, Button, TextInput, AsyncStorage } from 'react-native';
class SettingsScreen extends Component {
static navigationOptions = {
title: 'Settings',
};
constructor(props) {
super(props);
this.state = {
text: ''
};
}
saveData() {
AsyncStorage.setItem('lang', this.state.text);
this.props.langHandler(this.state.text);
}
render() {
return (
<View style={styles.container}>
<View>
<TextInput onChangeText={(text) => this.setState({ text })} />
<Button title='set' onPress={() => this.saveData()} />
</View>
</View>
);
}
}
我正在尝试设置
const RootNav = StackNavigator({
Home: { screen: HomeScreen },
Settings: { screen: props => <SettingsScreen (...props) />}
但是不起作用。 也许我需要使用 Redux?但如果有可能避免这种情况更好:) 也许我应该以不同的方式做所有事情?
感谢您的宝贵时间。 最好的问候
您要找的是screenProps
。您必须将 langHandler
添加到 RootNav
screenProps。
render() {
const screenProps = {
langHandler: this.langHandler,
};
if (this.state.isLoadingComplete) {
return (
<MenuProvider>
<RootNav screenProps={screenProps} />
</MenuProvider>);
}
return <View />;
}
然后您就可以在 SettingsScreen
this.props.screenProps.langHandler
访问 langHandler
saveData() {
AsyncStorage.setItem('lang', this.state.text);
this.props.screenProps.langHandler(this.state.text);
}