除非指定了服务器值,否则Apollo GraphQL客户端解析器将无法解析

时间:2019-08-05 15:08:03

标签: javascript reactjs graphql apollo

我正在使用Apollo GraphQL客户端执行一些相当复杂的操作。到目前为止,一切都很好,但是我正在解决一个烦人的问题。我试图异步设置一些解析器(解析器取决于其他一些异步应用程序状态)。我不确定这是否是最好的方法,但是下面是一些相关代码:

Apollo客户端设置:

const cache = new InMemoryCache();

const client = new ApolloClient({
  cache,
  link: new HttpLink({
    uri: process.env.REACT_APP_GRAPH_NODE_URI
  }),
  resolvers,
  typeDefs
});

const defaults = {
  loggedInUser: "",
  guildBankValue: "0",
  shareValue: "0",
  totalShares: "0",
  currentPeriod: "0",
  exchangeRate: "0",
  proposalQueueLength: "0",
  totalPoolShares: "0",
  poolValue: "0",
  poolShareValue: "0"
}
cache.writeData({
  data: { ...defaults, loggedInUser: window.localStorage.getItem("loggedInUser") || "" }
});

生成客户端解析器的功能:

function getLocalResolvers(medianizer, moloch, molochPool, token) {
  return {
    Query: {
      guildBankValue: async () => {
        const value = (await token.balanceOf(process.env.REACT_APP_GUILD_BANK_ADDRESS)).toString();
        return value
      },
      totalShares: async () => {
        const shares = (await moloch.totalShares()).toString();
        return shares
      },
      currentPeriod: async () => {
        const period = (await moloch.getCurrentPeriod()).toString();
        return period
      },
      exchangeRate: async () => {
        const rate = (await medianizer.compute())[0];
        return utils.bigNumberify(rate).toString();
      },
      proposalQueueLength: async () => {
        const length = (await moloch.getProposalQueueLength()).toString();
        return length
      },
      totalPoolShares: async () => {
        const shares = (await molochPool.totalPoolShares()).toString()
        return shares
      },
      poolValue: async () => {
        const value = (await token.balanceOf(process.env.REACT_APP_MOLOCH_POOL_ADDRESS)).toString()
        return value
      },
    }
  };
}

我在其中添加解析器的应用入口点:

class App extends React.Component {
  state = {
    restored: false,
  };

  async componentWillMount() {
    // await persistor.restore();
    await this.populateData(true);
    this.setState({ restored: true });
  }

  async populateData(refetch) {
    let {
      data: { loggedInUser }
    } = await client.query({
      query: IS_LOGGED_IN
    });

    // make sure logged in metamask user is the one that's saved to storage
    if (loggedInUser) {
      await initWeb3(client);
    }

    const medianizer = await getMedianizer(loggedInUser);
    const moloch = await getMoloch();
    const molochPool = await getMolochPool();
    const token = await getToken();

    client.addResolvers(getLocalResolvers(medianizer, moloch, molochPool, token))

App组件的渲染方法:

render() {
    const { restored } = this.state;
    return restored ? (
      <ApolloProvider client={client}>
        <Router basename={process.env.PUBLIC_URL}>
          <Query query={IS_LOGGED_IN}>
            {loggedInUserData => {
              return (
                <>
                  <Background />
                  <Header loggedInUser={loggedInUserData.data.loggedInUser} client={client} populateData={this.populateData} />
                  <Wrapper>
                    <Switch>
                      <Route
                        exact
                        path="/"
                        render={props => <Home {...props} loggedInUser={loggedInUserData.data.loggedInUser} pageQueriesLoading={!restored} />}
                      />
                      <Route
                        path="/proposals"
                        render={props => <ProposalList {...props} loggedInUser={loggedInUserData.data.loggedInUser} pageQueriesLoading={!restored} />}
                      />
                      <Route
                        path="/members"
                        render={props => <MemberList {...props} loggedInUser={loggedInUserData.data.loggedInUser} pageQueriesLoading={!restored} />}
                      />
                      <Route
                        path="/proposalsubmission"
                        render={props =>
                          loggedInUserData.data.loggedInUser ? (
                            <ProposalSubmission {...props} loggedInUser={loggedInUserData.data.loggedInUser} pageQueriesLoading={!restored} />
                          ) : (
                            <Redirect to={{ pathname: "/" }} />
                          )
                        }
                      />
                      <Route
                        path="/pool"
                        component={props => <Pool {...props} loggedInUser={loggedInUserData.data.loggedInUser} pageQueriesLoading={!restored} />}
                      />
                      <Route
                        path="/pool-members"
                        render={props => (
                          <PoolMemberListView {...props} loggedInUser={loggedInUserData.data.loggedInUser} pageQueriesLoading={!restored} />
                        )}
                      />
                      <Route
                        component={props => <Home {...props} loggedInUser={loggedInUserData.data.loggedInUser} pageQueriesLoading={!restored} />}
                      />
                    </Switch>
                  </Wrapper>
                  <ToastMessage.Provider ref={node => (window.toastProvider = node)} />
                </>
              );
            }}
          </Query>
        </Router>
      </ApolloProvider>
    ) : (
      <>
        <Background />
        <Dimmer active>
          <Loader size="massive" />
        </Dimmer>
      </>
    );
  }

我面临的问题是,当我加载主页(/路由)时,解析器不会触发,我只会得到默认值。当我导航到应用程序中的另一个页面时,解析器实际上会触发,然后我可以返回主页并查看更新的数据。我不知道为什么会这样。如果我直接进入/pool路线,则应用会加载正确的数据。

该项目是开源的,请随时查看源代码:https://github.com/MolochVentures/moloch-monorepo/tree/resolvers

感谢您的帮助!

编辑:删除了apollo-link-state包并更新了客户端设置代码,同一件事正在发生。

Edit2:非常奇怪,我发现如果我在GraphQL查询中添加非客户端值,则解析器可以正确调用,即:

// this query works
const GET_POOL_METADATA = gql`
  {
    poolValue @client
    exchangeRate @client
    proposals(first: 1, where: { processed: true }, orderBy: proposalIndex, orderDirection: desc) {
      proposalIndex
    }
    totalShares @client
    guildBankValue @client
  }
`;

// this one doesnt
const GET_POOL_METADATA = gql`
  {
    poolValue @client
    exchangeRate @client
    totalShares @client
    guildBankValue @client
  }
`;

我将更改标题以反映这一点。

0 个答案:

没有答案