I am using React Apollo to work with a GaphQL backend. The function I am creating allows users to edit the admin permissions of another user.
I have two components. One component contains the React Apollo logic, including the query and the mutation components. When this component is rendered a prop that is passed down from a match parameter in the router specifies what admin to get the permissions of which is used in the GraphQL query. When the data required for the admin permissions component is retrieved it is passed as a prop to the child component which sets the initial state based on the prop. The child component contains no React Apollo logic and simply contains checkboxes and other inputs that update the state of the component as they are changed. When clicking the save changes button the parent's mutation function is called passing the newly updated permissions to insert variables into the mutation query.
The issue that I am facing is that sometimes the state does not change depending on the props. For example, admin 1 is accessed, the router then updates the URL when a button is clicked to access admin 2. It works up to this point. The router then updates the URL again when a button is clicked to access admin 1, admin 2 is still shown in the child component, despite the props being updated with the new values. Note the constructor of the child component is not called again.
Any suggestions on how I can ensure that when the data produced by the GraphQL query displays the correct child componenet instance? Furthermore, any suggestions on how the structure of this componenet can be improved.
render(){
if(this.props.steamID === null) return null;
const QUERY_VARIABLES = {
serverID: this.props.serverID,
selectedAdminSteamID: this.props.steamID,
currentAdminSteamID: Auth.claim.steamID
};
return (
<Query
query={QUERY}
variables={QUERY_VARIABLES}
>
{({ loading, error, data }) => {
if (loading) return ( ... );
if (error) return ( ... );
if(!data.server.selectedAdmin) return ( ... );
return (
<Mutation
mutation={MUTATION}
update={(cache, { data: { updateAdminPermission } }) => {
const data = cache.readQuery({ query: QUERY, variables: QUERY_VARIABLES });
data.server.selectedAdmin = updateAdminPermission;
cache.writeQuery({ query: QUERY, variables: QUERY_VARIABLES, data: data, });
}}
>
{(updateAdminPermission, { loading, error }) => (
<>
<AdminPermissions
serverID={this.props.serverID}
steamID={this.props.steamID}
selectedAdmin={data.server.selectedAdmin}
currentAdmin={data.server.currentAdmin}
updatePermissionFunction={(variables) => {
updateAdminPermission({ variables })
}}
updatePermissionLoading={loading}
/>
<GraphQLErrorModal error={error} />
</>
)}
</Mutation>
);
}}
</Query>
);
}
class AdminPermissions extends React.Component{
constructor(props){
super();
this.state = props.selectedAdmin;
this.guid = React.createRef();
this.updatePermission = this.updatePermission.bind(this);
this.saveChanges = this.saveChanges.bind(this);
}
updatePermission(changedPermission, value){
if(changedPermission === 'manageAssignPermissions' && value > 0){
for(let permission of panelPermissions.concat(gamePermissions)){
if(permission.permission === 'manageAssignPermissions') continue;
this.setState({ [permission.permission]: 2 });
}
}
this.setState({ [changedPermission]: value });
}
saveChanges(){
this.props.updatePermissionFunction({
serverID: this.props.serverID,
steamID: this.props.steamID,
guid: this.guid.current.value,
...this.state
});
}
render(){
// renders pairs of checkboxes with checked value based on state and on change event that calls update permissions method passing the name of the associated permission and a value that is calculated based on which boxes in the pair are ticked.
}
}
Query (Update)
query AdminPermission($serverID: Int!, $selectedAdminSteamID: String!, $currentAdminSteamID: String!) {
server(id: $serverID) {
id
selectedAdmin: adminPermission(steamID: $selectedAdminSteamID) {
_id
admin {
_id
steamID
displayName
avatar
}
player {
_id
guid
}
manageAssignPermissions
viewAdminPermissions
...
}
currentAdmin: adminPermission(steamID: $currentAdminSteamID) {
_id
admin {
_id
steamID
}
manageAssignPermissions
viewAdminPermissions
...
}
}
}
fetchPolicy='cache-and-network'
to your<Query>
– Fraction