【发布时间】:2019-10-11 04:48:51
【问题描述】:
我正在使用 React Apollo 来处理 GaphQL 后端。我正在创建的功能允许用户编辑另一个用户的管理员权限。
我有两个组件。一个组件包含 React Apollo 逻辑,包括查询和突变组件。当这个组件被渲染时,从路由器中的 match 参数向下传递的 prop 指定在 GraphQL 查询中使用哪个管理员来获取其权限。当检索到管理员权限组件所需的数据时,它将作为道具传递给子组件,该子组件根据该道具设置初始状态。子组件不包含 React Apollo 逻辑,仅包含复选框和其他输入,这些输入会在组件状态发生更改时更新它们。单击保存更改按钮时,将调用父级的变异函数,传递新更新的权限以将变量插入到变异查询中。
我面临的问题是,有时状态不会根据道具而改变。例如,访问管理员 1,然后路由器会在单击按钮以访问管理员 2 时更新 URL。它一直工作到此为止。然后,当单击按钮访问 admin 1 时,路由器会再次更新 URL,尽管 props 已使用新值更新,但 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
...
}
}
}
【问题讨论】:
-
您发送的实际查询是什么?
-
查询的内容并不真正相关,但它基本上会获取一组属性,即 0、1 或 2 以及有关管理员的一些附加属性,例如他们的显示名称、头像等。
-
尝试将
fetchPolicy='cache-and-network'添加到您的<Query> -
@ThomasSmyth 如果查询的内容导致您的查询未正确缓存,则它可能是相关的。大多数情况下,这类问题是由于 Apollo 的缓存规范化造成的。
-
@DanielRearden 我很抱歉,我没有意识到这个问题是由于缓存造成的。
标签: javascript reactjs react-apollo