我有一个父母和一个孩子,我必须确保父亲中包含的孩子部分可以引用他。
例如,在子按钮上,我要调用父控件中使用的openDrawer()方法。
我试图通过道具将父母对孩子的引用传递给孩子,但这不起作用。
我在哪里做错了?
我该怎么办?
父母:
import * as React from 'react';
import { StyleSheet, View, Text, ToastAndroid, Button, Toolbar } from 'react-native';
import NavigationDrawerLayout from 'react-native-navigation-drawer-layout';
import Homepage from './page/Homepage';
import PageOne from './page/pageOne';
import PageTwo from './page/pageTwo';
export default class App extends React.Component {
constructor() {
super();
this.state = {
menu: '',
type: '',
drawer: ''
};
}
render() {
return (
<NavigationDrawerLayout
ref={_drawer => (this.drawer = _drawer)}
//ref={(_drawer) => this.setState({drawer:_drawer})}
percent={75}
//statusBar="#008cff"
//statusBarTransparency={0.3}
type={this.state.type}
drawerPosition="left"
selected="opt3"
window="menu"
color="#fff"
backgroundColor="#303030" //303030
imageBackground="https://c.wallhere.com/photos/aa/44/glare_colorful_bright_circles-679384.jpg!d"
first={'username'}
second={'joined'}
account={[
{
username: 'james.bond',
name: 'James Bond',
email: 'james.bond.xx@xxx.xxx',
image:
'https://cdn1.iconfinder.com/data/icons/avatar-2-2/512/Casual_Man_2-512.png',
joined: 'Joined at Jun 21, 2021',
badgeText: '100',
badgeColor: '#fff',
badgeBackground: '#303030',
circle: ['transparent', 'transparent'],
},
{
username: 'sherlock.holmes',
name: 'Sherlock Holmes',
email: 'sherlock.holmes.xx@xxx.xxx',
badgeText: '100',
badgeColor: '#fff',
badgeBackground: '#303030',
circle: ['#fff000', 'transparent', '#00ffd0'],
},
{
name: 'Shinichi Kudo',
email: 'shinichi.kudo.xx@xxx.xxx',
image:
'https://cdn1.iconfinder.com/data/icons/avatar-2-2/512/Casual_Man_3-512.png',
badgeText: '21',
badgeColor: '#fff',
badgeBackground: '#25dbd2',
joined: 'Joined at Jun 31, 2021',
circle: ['transparent', 'transparent'],
},
{
name: 'Arthur Conan Doyle',
email: 'arthur.conan.doyle.xx@xxx.xxx',
image:
'https://cdn0.iconfinder.com/data/icons/user-interface-vol-3-12/66/68-512.png',
circle: ['transparent', 'transparent'],
},
]}
badgeFunction={e => {
return e > 99 ? '99+' : e;
}}
menu={[
{
type: 'menu',
name: 'opt0',
backgroundLarge: 'transparent',
backgroundLargeFocus: 'transparent',
backgroundSmall: 'rgba(13, 71, 161, 0.5)',
backgroundSmallFocus: 'rgba(213, 0, 0, 0.5)',
iconLeft: 'apps',
iconLeftColor: '#c1c1c1',
iconLeftColorFocus: '#4CAF50',
title: 'Le mie app e i miei giochi',
titleColor: '#000000',
titleColorFocus: '#4CAF50',
badgeText: '100',
badgeColor: '#ffffff',
badgeBackground: '#1194ff',
iconRight: 'exit-to-app',
iconRightColor: '#4CAF50',
iconRightColorFocus: '#EF6C00',
close: false,
},
{
type: 'menu',
name: 'opt3',
title: 'Abbonamenti',
backgroundLarge: '#4286f4',
backgroundLargeFocus: '#34ed6b',
backgroundSmallFocus: 'rgba(213, 0, 0, 0.5)',
iconLeft: 'apps',
iconLeftColor: '#c1c1c1',
iconLeftColorFocus: '#4CAF50',
badgeText: '100',
badgeColor: '#ffffff',
badgeBackground: '#1194ff',
iconRight: 'exit-to-app',
iconRightColor: '#4CAF50',
iconRightColorFocus: '#EF6C00',
},
]}
onPress={e => {
ToastAndroid.show("Title: "+e.title+" * "+"Name: "+e.name,ToastAndroid.SHORT);
console.log('Menu:', e);
var type = e.name == 'opt2' ? 'simple' : '';
this.setState({ menu: e.title, type });
}}>
<Homepage drawer={this.drawer} />
</NavigationDrawerLayout>
);
}
}
const styles = StyleSheet.create({});
孩子:
import * as React from 'react';
import { Text, View, Button } from 'react-native';
export default class Homepage extends React.Component {
render() {
const {drawer} = this.props;
return (
<View
style={{
flex: 1,
//alignItems: 'flex-end',
}}>
<Text style={{ marginTop: 25, marginRight: 5, textAlign: 'right' }}>Hello World!</Text>
<Text style={{ marginTop: 25, marginRight: 5, textAlign: 'right' }}>
State: !
</Text>
<Button
onPress={()=drawer.openDrawer()}
title="Open"
color="#4286f4"
/>
</View>
);
}
}
答案 0 :(得分:0)
通常,孩子不应该认识父母。在这种情况下,传递的不是父(App
)引用,而是App
的另一个子引用this.drawer
。
这里的问题是使用了不推荐的ref函数ref={_drawer => (this.drawer = _drawer)}
。这会导致竞争状态,因为this.drawer
在分配给引用之前已传递给Homepage
,所以它是未定义的。
应该是:
this.drawerRef = React.createRef();
...
<NavigationDrawerLayout ref={this.drawerRef} .../>
...
<Homepage drawerRef={this.drawerRef} />
一旦安装NavigationDrawerLayout
,drawerRef.current
就被分配了一个实例,并且可以使用:
<Button onPress={()=drawerRef.current.openDrawer()} />
通过ref会破坏封装并在可能避免的地方提供紧密的耦合。 Homepage
确实不需要访问整个抽屉。这通常在React中通过传递函数prop来解决:
<Homepage openDrawer={() => this.drawerRef.current.openDrawer()} />
答案 1 :(得分:0)
解决方案1
您可以将相关方法直接传递给您的孩子。我喜欢这个。
import * as React from 'react';
import { StyleSheet, View, Text, ToastAndroid, Button, Toolbar } from 'react-native';
import NavigationDrawerLayout from 'react-native-navigation-drawer-layout';
import Homepage from './page/Homepage';
import PageOne from './page/pageOne';
import PageTwo from './page/pageTwo';
export default class App extends React.Component {
constructor() {
super();
this.state = {
menu: '',
type: '',
drawer: ''
};
this.openDrawer = this.openDrawer.bind(this);
}
openDrawer() {
// ...
}
render() {
return (
<NavigationDrawerLayout
ref={_drawer => (this.drawer = _drawer)}
//ref={(_drawer) => this.setState({drawer:_drawer})}
percent={75}
//statusBar="#008cff"
//statusBarTransparency={0.3}
type={this.state.type}
drawerPosition="left"
selected="opt3"
window="menu"
color="#fff"
backgroundColor="#303030" //303030
imageBackground="https://c.wallhere.com/photos/aa/44/glare_colorful_bright_circles-679384.jpg!d"
first={'username'}
second={'joined'}
account={[
{
username: 'james.bond',
name: 'James Bond',
email: 'james.bond.xx@xxx.xxx',
image:
'https://cdn1.iconfinder.com/data/icons/avatar-2-2/512/Casual_Man_2-512.png',
joined: 'Joined at Jun 21, 2021',
badgeText: '100',
badgeColor: '#fff',
badgeBackground: '#303030',
circle: ['transparent', 'transparent'],
},
{
username: 'sherlock.holmes',
name: 'Sherlock Holmes',
email: 'sherlock.holmes.xx@xxx.xxx',
badgeText: '100',
badgeColor: '#fff',
badgeBackground: '#303030',
circle: ['#fff000', 'transparent', '#00ffd0'],
},
{
name: 'Shinichi Kudo',
email: 'shinichi.kudo.xx@xxx.xxx',
image:
'https://cdn1.iconfinder.com/data/icons/avatar-2-2/512/Casual_Man_3-512.png',
badgeText: '21',
badgeColor: '#fff',
badgeBackground: '#25dbd2',
joined: 'Joined at Jun 31, 2021',
circle: ['transparent', 'transparent'],
},
{
name: 'Arthur Conan Doyle',
email: 'arthur.conan.doyle.xx@xxx.xxx',
image:
'https://cdn0.iconfinder.com/data/icons/user-interface-vol-3-12/66/68-512.png',
circle: ['transparent', 'transparent'],
},
]}
badgeFunction={e => {
return e > 99 ? '99+' : e;
}}
menu={[
{
type: 'menu',
name: 'opt0',
backgroundLarge: 'transparent',
backgroundLargeFocus: 'transparent',
backgroundSmall: 'rgba(13, 71, 161, 0.5)',
backgroundSmallFocus: 'rgba(213, 0, 0, 0.5)',
iconLeft: 'apps',
iconLeftColor: '#c1c1c1',
iconLeftColorFocus: '#4CAF50',
title: 'Le mie app e i miei giochi',
titleColor: '#000000',
titleColorFocus: '#4CAF50',
badgeText: '100',
badgeColor: '#ffffff',
badgeBackground: '#1194ff',
iconRight: 'exit-to-app',
iconRightColor: '#4CAF50',
iconRightColorFocus: '#EF6C00',
close: false,
},
{
type: 'menu',
name: 'opt3',
title: 'Abbonamenti',
backgroundLarge: '#4286f4',
backgroundLargeFocus: '#34ed6b',
backgroundSmallFocus: 'rgba(213, 0, 0, 0.5)',
iconLeft: 'apps',
iconLeftColor: '#c1c1c1',
iconLeftColorFocus: '#4CAF50',
badgeText: '100',
badgeColor: '#ffffff',
badgeBackground: '#1194ff',
iconRight: 'exit-to-app',
iconRightColor: '#4CAF50',
iconRightColorFocus: '#EF6C00',
},
]}
onPress={e => {
ToastAndroid.show("Title: "+e.title+" * "+"Name: "+e.name,ToastAndroid.SHORT);
console.log('Menu:', e);
var type = e.name == 'opt2' ? 'simple' : '';
this.setState({ menu: e.title, type });
}}>
<Homepage openDrawer={this.openDrawer} />
</NavigationDrawerLayout>
);
}
}
const styles = StyleSheet.create({});
解决方案2
您可以直接使用React.createRef()
。
URL:https://reactjs.org/docs/refs-and-the-dom.html
import * as React from 'react';
import { StyleSheet, View, Text, ToastAndroid, Button, Toolbar } from 'react-native';
import NavigationDrawerLayout from 'react-native-navigation-drawer-layout';
import Homepage from './page/Homepage';
import PageOne from './page/pageOne';
import PageTwo from './page/pageTwo';
export default class App extends React.Component {
constructor() {
super();
this.state = {
menu: '',
type: '',
drawer: ''
};
this.myRef = React.createRef();
}
render() {
return (
<NavigationDrawerLayout
ref={this.myRef}
//ref={(_drawer) => this.setState({drawer:_drawer})}
percent={75}
//statusBar="#008cff"
//statusBarTransparency={0.3}
type={this.state.type}
drawerPosition="left"
selected="opt3"
window="menu"
color="#fff"
backgroundColor="#303030" //303030
imageBackground="https://c.wallhere.com/photos/aa/44/glare_colorful_bright_circles-679384.jpg!d"
first={'username'}
second={'joined'}
account={[
{
username: 'james.bond',
name: 'James Bond',
email: 'james.bond.xx@xxx.xxx',
image:
'https://cdn1.iconfinder.com/data/icons/avatar-2-2/512/Casual_Man_2-512.png',
joined: 'Joined at Jun 21, 2021',
badgeText: '100',
badgeColor: '#fff',
badgeBackground: '#303030',
circle: ['transparent', 'transparent'],
},
{
username: 'sherlock.holmes',
name: 'Sherlock Holmes',
email: 'sherlock.holmes.xx@xxx.xxx',
badgeText: '100',
badgeColor: '#fff',
badgeBackground: '#303030',
circle: ['#fff000', 'transparent', '#00ffd0'],
},
{
name: 'Shinichi Kudo',
email: 'shinichi.kudo.xx@xxx.xxx',
image:
'https://cdn1.iconfinder.com/data/icons/avatar-2-2/512/Casual_Man_3-512.png',
badgeText: '21',
badgeColor: '#fff',
badgeBackground: '#25dbd2',
joined: 'Joined at Jun 31, 2021',
circle: ['transparent', 'transparent'],
},
{
name: 'Arthur Conan Doyle',
email: 'arthur.conan.doyle.xx@xxx.xxx',
image:
'https://cdn0.iconfinder.com/data/icons/user-interface-vol-3-12/66/68-512.png',
circle: ['transparent', 'transparent'],
},
]}
badgeFunction={e => {
return e > 99 ? '99+' : e;
}}
menu={[
{
type: 'menu',
name: 'opt0',
backgroundLarge: 'transparent',
backgroundLargeFocus: 'transparent',
backgroundSmall: 'rgba(13, 71, 161, 0.5)',
backgroundSmallFocus: 'rgba(213, 0, 0, 0.5)',
iconLeft: 'apps',
iconLeftColor: '#c1c1c1',
iconLeftColorFocus: '#4CAF50',
title: 'Le mie app e i miei giochi',
titleColor: '#000000',
titleColorFocus: '#4CAF50',
badgeText: '100',
badgeColor: '#ffffff',
badgeBackground: '#1194ff',
iconRight: 'exit-to-app',
iconRightColor: '#4CAF50',
iconRightColorFocus: '#EF6C00',
close: false,
},
{
type: 'menu',
name: 'opt3',
title: 'Abbonamenti',
backgroundLarge: '#4286f4',
backgroundLargeFocus: '#34ed6b',
backgroundSmallFocus: 'rgba(213, 0, 0, 0.5)',
iconLeft: 'apps',
iconLeftColor: '#c1c1c1',
iconLeftColorFocus: '#4CAF50',
badgeText: '100',
badgeColor: '#ffffff',
badgeBackground: '#1194ff',
iconRight: 'exit-to-app',
iconRightColor: '#4CAF50',
iconRightColorFocus: '#EF6C00',
},
]}
onPress={e => {
ToastAndroid.show("Title: "+e.title+" * "+"Name: "+e.name,ToastAndroid.SHORT);
console.log('Menu:', e);
var type = e.name == 'opt2' ? 'simple' : '';
this.setState({ menu: e.title, type });
}}>
<Homepage drawer={this.myRef.current} />
</NavigationDrawerLayout>
);
}
}
const styles = StyleSheet.create({});