我正在使用React Apollo与GaphQL后端一起使用。我正在创建的功能允许用户编辑其他用户的管理员权限。
我有两个组成部分。一个组件包含React Apollo逻辑,包括查询和变异组件。呈现此组件时,将从路由器中的match参数向下传递的道具指定在GraphQL查询中使用哪个管理员来获取其权限。检索到管理权限组件所需的数据后,它将作为道具传递给子组件,该子组件根据该道具设置初始状态。子组件不包含React Apollo逻辑,仅包含复选框和其他输入,这些复选框和其他输入会在更改组件时更新其状态。单击“保存更改”按钮时,将调用父级的变异函数,传递新近更新的权限,以将变量插入变异查询中。
我面临的问题是,有时候状态不会因道具而改变。例如,访问admin 1,然后单击按钮访问admin 2时,路由器将更新URL。然后,尽管通过新值更新了道具,但单击按钮以访问管理员1时,路由器仍再次更新URL,管理员2仍显示在子组件中。请注意,不会再次调用子组件的构造函数。
关于如何确保GraphQL查询生成的数据何时显示正确的子componenet实例的任何建议?此外,关于如何改进该组件网络的任何建议。
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)
您必须将Query
的{{1}}设置为fetchPolicy
,默认情况下为cache-and-network
:
cache-first
如果您阅读documentation:
缓存优先:这是我们始终尝试读取的默认值 首先从缓存中获取数据。如果需要所有数据来满足您的要求 查询在缓存中,然后将返回数据。阿波罗将 仅当无法获得缓存结果时才从网络获取。这个 提取策略旨在最大程度地减少以下情况下发送的网络请求数量: 渲染您的组件。
缓存和网络:此提取策略将 让Apollo首先尝试从您的缓存中读取数据。如果所有数据 满足您的查询需要的是在缓存中,然后该数据将 回到。但是,无论是否包含完整数据 您的缓存,此fetchPolicy将始终通过网络执行查询 不同于cache-first的界面,该界面仅在以下情况下执行查询: 查询数据不在您的缓存中。此提取策略为用户优化 在快速响应的同时还尝试保留缓存的数据 与服务器数据保持一致,但需要额外的网络 请求。