Skip to content

Commit 956aaa8

Browse files
mdebbarJames Baxley
authored andcommitted
Support passing updater function to setState in SSR mode (apollographql#1263)
* Support setting state via callback in SSR mode * Add change to Changelog.md * Support full signature of state updater
1 parent 63cf49f commit 956aaa8

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

Changelog.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
### vNext
44
- fix skip on component update.
55
- Fix: ensure `client` option can be used with mutation query [#1145](https://github.com/apollographql/react-apollo/pull/1145)
6-
76
- Made `OptionProps.data`'s `TResult` partial [#1231](https://github.com/apollographql/react-apollo/pull/1231)
7+
- Support passing an updater function to `setState` in SSR mode [#1263](https://github.com/apollographql/react-apollo/pull/1263)
88
- Support arrays being returned from render in SSR [#1158](https://github.com/apollographql/react-apollo/pull/1158)
99

1010
### 1.4.16

src/server.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ export function walkTree(
6666
// however, we don't need to re-render as well only support setState in
6767
// componentWillMount, which happens *before* render).
6868
instance.setState = newState => {
69+
if (typeof newState === 'function') {
70+
newState = newState(instance.state, instance.props, instance.context);
71+
}
6972
instance.state = assign({}, instance.state, newState);
7073
};
7174

test/react-web/server/index.test.tsx

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,72 @@ describe('SSR', () => {
646646
.catch(console.error);
647647
});
648648

649+
it('should allow for setting state via an updater function', done => {
650+
const query = gql`
651+
query user($id: ID) {
652+
currentUser(id: $id) {
653+
firstName
654+
}
655+
}
656+
`;
657+
const data = { currentUser: { firstName: 'James' } };
658+
const variables = { id: 1 };
659+
const networkInterface = mockNetworkInterface({
660+
request: { query, variables },
661+
result: { data },
662+
delay: 50,
663+
});
664+
const apolloClient = new ApolloClient({
665+
networkInterface,
666+
addTypename: false,
667+
});
668+
669+
@graphql(query, { name: 'user' })
670+
class Element extends React.Component<any, any> {
671+
state = {
672+
thing: 1,
673+
userId: null,
674+
client: null,
675+
};
676+
677+
componentWillMount() {
678+
this.setState((state, props, context) => ({
679+
thing: state.thing + 1,
680+
userId: props.id,
681+
client: context.client,
682+
}));
683+
}
684+
685+
render() {
686+
const { user, id } = this.props;
687+
expect(this.state.thing).toBe(2);
688+
expect(this.state.userId).toBe(id);
689+
expect(this.state.client).toBe(apolloClient);
690+
return (
691+
<div>{user.loading ? 'loading' : user.currentUser.firstName}</div>
692+
693+
);
694+
}
695+
}
696+
697+
const app = (
698+
<ApolloProvider client={apolloClient}>
699+
<Element id={1} />
700+
</ApolloProvider>
701+
);
702+
703+
getDataFromTree(app)
704+
.then(() => {
705+
const initialState = apolloClient.store.getState();
706+
expect(initialState.apollo.data).toBeTruthy();
707+
expect(
708+
initialState.apollo.data['$ROOT_QUERY.currentUser({"id":1})'],
709+
).toBeTruthy();
710+
done();
711+
})
712+
.catch(console.error);
713+
});
714+
649715
it("shouldn't run queries if ssr is turned to off", () => {
650716
const query = gql`
651717
query user($id: ID) {

0 commit comments

Comments
 (0)