Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs Apollo客户端解析器只触发一次_Reactjs_React Apollo_Apollo Client_Resolver - Fatal编程技术网

Reactjs Apollo客户端解析器只触发一次

Reactjs Apollo客户端解析器只触发一次,reactjs,react-apollo,apollo-client,resolver,Reactjs,React Apollo,Apollo Client,Resolver,我目前正在开发一个react应用程序,它使用GraphQL后端并具有额外的本地状态。我使用解析程序解析随时间变化的本地字段,但解析程序只触发一次 我尝试使用cache.readQuery重新运行查询,以防本地字段发生更改,但它似乎没有像我预期的那样工作 export const resolvers = { Query: { resolvedDevice: (obj, args, { cache }, info) => { const data = cache.rea

我目前正在开发一个react应用程序,它使用GraphQL后端并具有额外的本地状态。我使用解析程序解析随时间变化的本地字段,但解析程序只触发一次

我尝试使用cache.readQuery重新运行查询,以防本地字段发生更改,但它似乎没有像我预期的那样工作

export const resolvers = {
  Query: {
    resolvedDevice: (obj, args, { cache }, info) => {
      const data = cache.readQuery({
        query: gql`
          query {
            selectedDevice @client
          }
        `
      });

      // do stuff with the data
    }
  },
  Mutation: {
    selectDevice: (_, { id }, { cache }) => {
      cache.writeData({ data: { selectedDevice: id } });
    }
  }
};

const query = gql`
  query GetResolvedDevice {
    resolvedDevice @client
  }
`;

在这种情况下,解析程序中的“resolvedDevice”只执行一次,即使我通过“selectDevice”变异缓存。我预计,当通过变异更改本地状态时,解析程序也会再次运行,因为缓存正在更改

以下是执行查询的代码:

const ModalContainer = props => {
  const { loading, error, data } = useQuery(query);

  if (loading || error) {
    return null;
  }

  return (
    <Modal
      device={data.resolvedDevice}
    />
  );
};
const ModalContainer=props=>{
const{loading,error,data}=useQuery(查询);
如果(加载| |错误){
返回null;
}
返回(
);
};
在这个组件中,我在selectedDevice上运行一个变异:

export const SELECT_DEVICE = gql`
  mutation SelectDevice($id: String!) {
    selectDevice(id: $id) @client
  }
`;

const DevicesNoGeoContainer = () => {
  const [selectDevice] = useMutation(SELECT_DEVICE);

  return (
    <DevicesNoGeo
      onGeoClick={id => {
        selectDevice({ variables: { id } });
      }}
    />
  );
};
export const SELECT\u DEVICE=gql`
选择设备($id:String!){
选择设备(id:$id)@client
}
`;
const DevicesNoGeoContainer=()=>{
const[selectDevice]=使用变异(选择设备);
返回(
{
选择设备({变量:{id}});
}}
/>
);
};

Apollo知道当缓存中的值发生变化时,会更新从缓存中提取字段的监视查询。在这种情况下,查询中的字段由本地解析程序实现。这意味着Apollo没有可以订阅和响应特定查询的缓存条目。因此,第一个查询已经完成,除非在钩子结果上使用
refetch
显式地触发它,否则您不会得到查询的任何更新

解决这个问题的一种方法是在缓存中“持久化”派生字段,并在组件查询中使用缓存完成的字段。我们可以通过显式地查看源字段(<代码>选择设备),并且在处理程序中,将派生字段(<代码> RealvdEdvs/Cuff> >)写入缓存(我将继续使用您的字段名称,但如果您走这条路线,您可能会考虑重命名它,因为它似乎以其定义的方式命名)。 概念证明

export const resolvers = {
  Mutation: {
    selectDevice: (_, { id }, { cache }) => {
      cache.writeData({ data: { selectedDevice: id } });
    }
  }
};

const client = new ApolloClient({
  resolvers
});

const sourceQuery = gql`
  query {
    selectedDevice @client
  }`;

// watch the source field query and write resolvedDevice back to the cache at top-level
client.watchQuery({ query: sourceQuery }).subscribe(value =>
  client.writeData({ data: { resolvedDevice: doStuffWithTheData(value.data.selectedDevice) } });

const query = gql`
  query GetResolvedDevice {
    resolvedDevice @client
  }
`;
因为传递给
watchQuery
的查询中的字段存在于缓存中,所以每次更改都会调用处理程序,我们会将派生字段写入缓存作为响应。 由于
resolvedDevice
现在位于缓存中,因此查询它的组件现在将在每次更改时获得更新(这将在“upsteam”
selectedDevice
字段更改时进行)

现在,您可能不想实际将源字段监视查询放在顶层,因为无论是否使用渲染组件,它都会在应用程序启动时运行并监视。如果对一组本地州字段采用这种方法,这将特别糟糕。 我们正在研究一种方法,在该方法中,您可以声明性地定义派生字段及其实现函数:

export const derivedFields: {
  resolvedDevice: {
    fulfill: () => client.watchQuery({ query: sourceQuery }).subscribe(value =>
      client.writeData({ data: { resolvedDevice: doStuffWithTheData(value.data.selectedDevice),
  }
};
然后使用HOC让他们参与:

import { derivedFields } from './the-file-above';

export const withResolvedField = field => RenderingComponent => {
  return class ResolvedFieldWatcher extends Component {
    componentDidMount() {
      this.subscription = derivedFields[field].fulfill();
    }
    componentDidUnmount() {
      // I don't think this is actually how you unsubscribe, but there's
      // some way to do it
      this.subscription.cancel();
    }
    render() {
      return (
        <RenderingComponent {...this.props } />
      );
    }
  };
};

请注意,我在这里的结尾是非常假设的,我只是把它打出来,而不是把我们的实际代码拉下来。我们也回到了Apollo 2.5和React 2.6上,因此您可能必须调整钩子等的方法。但原则应该是相同的:通过查看缓存中源字段的查询来定义派生字段,然后将派生字段写回缓存。然后根据派生字段将源数据与组件呈现ui进行反应式级联。

查询不会自动更新。你能在运行查询/变异的地方发布代码吗?需要明确的是,所涉及的查询都是本地的,或者您正在从后端获取数据?这有帮助吗?抱歉,耽搁了这么久。非常感谢您的回答,非常有帮助。
export default withDerivedField('resolvedDevice')(ModalContainer);