javascript - React Apollo - 孩子没有根据结果变化进行更新
问题描述
我正在使用 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
...
}
}
}
解决方案
您必须将Query
's设置fetchPolicy
为cache-and-network
,默认情况下它是cache-first
:
<Query
query={QUERY}
variables={QUERY_VARIABLES}
fetchPolicy='cache-and-network'
>
如果您阅读 文档:
cache-first:这是我们总是首先尝试从缓存中读取数据的默认值。如果完成查询所需的所有数据都在缓存中,则将返回该数据。如果缓存的结果不可用,Apollo 只会从网络中获取。此获取策略旨在最大限度地减少渲染组件时发送的网络请求数量。
cache-and-network:此获取策略将让 Apollo 首先尝试从您的缓存中读取数据。如果完成查询所需的所有数据都在缓存中,则将返回该数据。但是,无论完整数据是否在您的缓存中,此 fetchPolicy 将始终使用网络接口执行查询,这与 cache-first 不同,后者仅在查询数据不在您的缓存中时才会执行您的查询。此获取策略优化了用户获得快速响应,同时还尝试以额外的网络请求为代价使缓存数据与您的服务器数据保持一致。
推荐阅读
- android - 即使在观察者被移除后,实时数据观察者也会被调用
- python - 对python中的部分数据框做一些处理
- firebase - 如何在 Firebase Functions shell 中运行 Pub-Sub 函数
- python - 如何在python中正确导入包?
- python - 如何在熊猫中旋转这个数据框
- python - 无法在 Python 中发出 HTTP 请求
- android - IndexOutOfBoundsException: Invalid index 0, size is 0. 我该如何解决这个问题
- c# - 如何解决 WACK 问题“发现错误:私有代码签名测试遇到以下错误:”
- javascript - Vuex状态在突变后不更新
- batch-file - 批量重命名文件,合并列.csv?