Я использую React Apollo для работы с бэкэндом GaphQL.Функция, которую я создаю, позволяет пользователям редактировать права администратора другого пользователя.
У меня есть два компонента.Один компонент содержит логику React Apollo, включая запрос и компоненты мутации.Когда этот компонент визуализируется, свойство, которое передается из параметра соответствия в маршрутизаторе, указывает, какой администратор для получения разрешений которого используется в запросе GraphQL.Когда данные, необходимые для компонента прав доступа администратора, извлекаются, они передаются в качестве подпорки дочернему компоненту, который устанавливает начальное состояние на основе подпорки.Дочерний компонент не содержит логику React Apollo и просто содержит флажки и другие входные данные, которые обновляют состояние компонента по мере его изменения.При нажатии кнопки «Сохранить изменения» вызывается функция мутации родителя, передавая недавно обновленные разрешения на вставку переменных в запрос на мутацию.
Проблема, с которой я сталкиваюсь, заключается в том, что иногда состояние не изменяется в зависимости от реквизита.Например, доступ к admin 1, маршрутизатор затем обновляет URL при нажатии кнопки для доступа к admin 2. Это работает до этого момента.Затем маршрутизатор снова обновляет URL-адрес при нажатии кнопки для доступа к admin 1, admin 2 по-прежнему отображается в дочернем компоненте, несмотря на то, что реквизиты обновляются с новыми значениями.Обратите внимание, что конструктор дочернего компонента больше не вызывается.
Есть предложения о том, как я могу гарантировать, что когда данные, генерируемые запросом GraphQL, отображают правильный экземпляр дочернего компонента?Кроме того, любые предложения о том, как можно улучшить структуру этого компонента.
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 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
...
}
}
}