2 min read

结合 React 和 GraphQL 的应用(Part 1/2)

自我挖坑ing

基础环境

高能预警:对于如此天坑,我建议是:我不入地狱谁入地狱。

前端: 对于GraphQL, 除非你打算手动fetch, 否则可选的目前是 Relay+GraphQL 或者 ApolloClient+GraphQL, 而我选择的是 ApolloClient+GraphQL。所以本片文章不会涉及到Relay的部分。

后端:后端选择比较多,都是提供API的部分,所以我local的环境是 Rails5,而测试时候我也会使用 Graph.cool 的服务和 Scaphold。

核心逻辑

这部分仅供对应 ApolloClient, Apollo Client 的核心逻辑就是,当前页面只要有过的Query,就坚决从本地获取数据。除非你手动指定再次Query。否则数据就从本地取。

所以比如说,如果在新建一个记录,然后再回到列表的时候,是一定需要,一定需要,手动更新UI的。如果更新一个记录,则并不需要。

获取数据

如果用到查询绑定了页面,如:export default graphql(FEED_QUERY) (List)

这种情况下实际上执行了两次query,第一次是loading,第二次才是finish的界面。所以在render()里面,,是需要有如下判断的:const { data } = this.props;if (data && data.loading) {
 return (
   <div>Loading</div>
 )
}if (data && data.error) {
 return <div>Error</div>
}// actually render after fetching here.

而且,在以上注释的位置,实际上,fetching的数据,还依然在fetching,这时候有些动作是不能做的,比如 setState()。

所以在这里我就遇到了一个很直接的问题,情况是,我需要获取了数据准备修改,然后把原来的数据初始化进 state 里面,然后页面表单每次 onChange的时候更新state。在state里面保存表单的信息,最后进行提交。

但是实际上constructor()中是初始化的,这时候数据是没有获取到的,所以需要等待数据fetch结束了以后才能setState。但是由于用了Apollo封装后的HOC,并不像手动更新可以在 ComponentDidMount()中间获取远程数据,这就是一个麻烦的问题。

最后我的办法是在ComponentDidUpdate里面进行判断,如果原始state为空则从props里面获取fetch来的f数据,否则本次更新则应该为界面触发的,则不会获取fetch来的数据。

我似乎没有找到更好的办法,如果有了解的朋友也可以告诉我更好的办法。


更新分割