我有一个抽屉组件,用户可以从权限页面设置菜单项的可见性。用户更新权限后,我无法使用最新菜单项更新抽屉组件。 当我重新加载应用程序或注销并登录时,它确实会更新。我正在寻找一种更新角色后刷新抽屉的方法。当前在BusinessRoleEdit页面上返回navigation.navigate('BusinessRoleList')不起作用。我想我必须在createstack导航器上添加“ addlistener”或以其他方式导航,但无法弄清楚如何。任何帮助将不胜感激。
Drawercomponent.jsx
import React, {useState,useEffect} from 'react';
import PropTypes from 'prop-types';
import { SafeAreaView, ScrollView, StyleSheet,View,TouchableOpacity } from 'react-native';
import { DrawerItems,createStackNavigator } from 'react-navigation';
import { Container, Content, Text, List, ListItem, Spinner, Left,Icon,Right,Thumbnail,Body,Separator } from "native-base";
import {Image,ImageBackground} from "react-native";
import logo from '../images/logofullwhite200.png';
import Collapsing from 'react-native-collapsing';
import { useApolloClient } from '@apollo/react-hooks';
import BUSINESSROLE_QUERY from '@gqlapp/businessrole-client-react/graphql/BusinessRoleQuery.graphql';
import CURRENT_USER_QUERY from '@gqlapp/user-client-react/graphql/CurrentUserQuery.graphql';
const DrawerComponent = (props,navigation) => {
const skippedItems = Object.keys(props.drawerItems).filter(name => props.drawerItems[name].skip);
const [selected, setSelected] = useState('');
const [permissions, setPermissions] = useState({});
const [permissionsUpdated, setPermissionsUpdated] = useState(false);
if (props.currentUser) {
let client = useApolloClient();
let _permissions = []
client.query({
query: BUSINESSROLE_QUERY,
variables: { id: props.currentUser.businessroleid}
}).then((br) => {
let businessrole = br.data.businessrole;
_permissions = JSON.parse(businessrole.permissions)
if(!permissionsUpdated) {
setPermissions(_permissions)
setPermissionsUpdated(true)
}
})
}
const RenderMenu = () => {
if (permissions) {
let menuElements = []
Object.keys(permissions).forEach(p => {
if(permissions[p].children && permissions[p].isChecked ) {
let subTitles = []
permissions[p].children.map(child=>{
if (child.isChecked) {
subTitles.push({name: child.nav, title: child.name, icon: child.icon})
}
})
menuElements.push(<Collapsing
selected={selected}
iconBarNameNormal={permissions[p].icon}
iconBarNameFocus={permissions[p].icon}
iconBarColorNormal="#0480CB"
title={permissions[p].navtitle}
color="#4CAF50"
showOnStart={false}
animateIconNameNormal="chevron-down"
animateIconNameFocus="chevron-up"
onPress={e => {
setSelected(e.name);
props.navigation.navigate(e.name);
}}
menu={subTitles}
/>)
}
})
return (<View>
{menuElements.map(elm =>{return elm})}
</View>)
} else {
return <Spinner color="blue" />
}
}
let client = useApolloClient();
let _permissions = []
client.query({ query: CURRENT_USER_QUERY }).then((cr) => {
let currentUser = cr.data.currentUser
client.query({
query: BUSINESSROLE_QUERY,
variables: { id: currentUser.businessroleid}
}).then((br) => {
let businessrole = br.data.businessrole;
_permissions = JSON.parse(businessrole.permissions)
})
})
return (
<View style={styles.flexcontainer}>
<View style={styles.firstBox}>
<ImageBackground
source={{
uri: "https://raw.githubusercontent.com/GeekyAnts/NativeBase-KitchenSink/master/assets/drawer-cover.png"
}}
style={{
height: 80,
alignSelf: "stretch",
justifyContent: "center",
alignItems: "center"
}}>
<Image
square
style={{ height: 50, width: 140 }}
source={logo}
/>
</ImageBackground>
</View>
<View style={styles.secondBox}>
<ScrollView>
<RenderMenu/>
</ScrollView>
</View>
<View style={styles.thirdBox}>
<ListItem avatar itemDivider >
<Left>
<Thumbnail small source={{ uri: 'https://secure.gravatar.com/avatar/843473dc1738adb0ef54d450243d8955?s=320&d=identicon' }} />
</Left>
<Body style={{borderBottomWidth: 0}}>
<Text>Caner Cakmak</Text>
<Text note numberOfLines={1}>My Grocery Retail Store</Text>
</Body>
<Right style={{borderBottomWidth: 0}}>
<Icon active name="log-out"/>
</Right>
</ListItem>
</View>
</View>
);
};
DrawerComponent.propTypes = {
onItemPress: PropTypes.func,
drawerItems: PropTypes.object,
currentUser: PropTypes.object
};
export default DrawerComponent;
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 20
},
flexcontainer: {
flex: 3,
},
firstBox: {
flex: 1
},
secondBox: {
flex: 8
},
thirdBox: {
flex: 1
}
});
Businessroledit.jsx
graphql(EDIT_BUSINESSROLE, {
props: ({ ownProps: { history, navigation }, mutate }) => ({
editBusinessRole: async (id, name, permissions,business_id) => {
await mutate({
variables: {
input: {
id,
name: name.trim(),
permissions:JSON.stringify(permissions),
business_id: parseInt(business_id)
}
}
});
if (history) {
return await history.push('/businessroles');
}
if (navigation) {
return navigation.navigate('BusinessRoleList');
}
}
})
})
userscreennavigator.jsx
import { createAppContainer, createDrawerNavigator } from 'react-navigation';
import React from 'react';
import PropTypes from 'prop-types';
import { pickBy } from 'lodash';
import { compose } from '@gqlapp/core-common';
import { DrawerComponent } from '@gqlapp/look-client-react-native';
import { withUser } from './Auth';
class UserScreenNavigator extends React.Component {
static propTypes = {
currentUser: PropTypes.object,
context: PropTypes.object,
currentUserLoading: PropTypes.bool.isRequired,
routeConfigs: PropTypes.object
};
businessRoleQuery = async (client: ApolloClient<any>) => {
const {currentUser } = this.props;
await client.readQuery({ query: BUSINESSROLE_QUERY, variables: { id: 1} }).then((user)=> {
return user
})
}
shouldComponentUpdate(nextProps) {
const { currentUserLoading, currentUser } = this.props;
/**
* After a user edits the profile the CurrentUser being updated in the State as well.
* That leads to the Navigator re-rendering and, as a result, takes the user back to the initial route.
* In order to let the user get back to his/her profile we need to prevent the Navigator
* re-render action after profile was edited
*/
return !(
!currentUserLoading &&
currentUser &&
nextProps.currentUser &&
currentUser.id === nextProps.currentUser.id &&
currentUser.role === nextProps.currentUser.role
);
}
navItemsFilter = () => {
const { currentUser, currentUserLoading, routeConfigs } = this.props;
const userFilter = value => {
if (!value.userInfo) return true;
const { showOnLogin, role } = value.userInfo;
return showOnLogin && (!role || (Array.isArray(role) ? role : [role]).includes(currentUser.role));
};
const guestFilter = value => !value.userInfo || (value.userInfo && !value.userInfo.showOnLogin);
return pickBy(routeConfigs, currentUser && !currentUserLoading ? userFilter : guestFilter);
};
getInitialRoute = () => {
const { currentUser } = this.props;
return currentUser ? 'Dashboard' : 'Login';
};
render() {
const { currentUser, currentUserLoading} = this.props;
const MainScreenNavigatorComponent = createAppContainer(
createDrawerNavigator(
{ ...this.navItemsFilter() },
{
// eslint-disable-next-line
contentComponent: props => <DrawerComponent {...props} currentUser={currentUser} drawerItems={this.props.routeConfigs} />,
initialRouteName: this.getInitialRoute()
}
)
);
return <MainScreenNavigatorComponent />;
}
}
const drawerNavigator = routeConfigs => {
const withRoutes = Component => {
const ownProps = { routeConfigs };
const WithRoutesComponent = ({ ...props }) => <Component {...props} {...ownProps} />;
return WithRoutesComponent;
};
return compose(
withUser,
withRoutes
)(UserScreenNavigator);
};
export default drawerNavigator;