我正在使用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
}
`;
我将更改标题以反映这一点。