Skip to content

Commit

Permalink
Merge pull request #130 from Shopify/fix-server-state
Browse files Browse the repository at this point in the history
fix: fix server state to use pathname
  • Loading branch information
blittle authored Nov 5, 2021
2 parents 46d1658 + 2c8b247 commit 53c1110
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function ServerStateRouter() {

useEffect(() => {
setIsNavigating(true);
setServerState('page', location.pathname);
setServerState('pathname', location.pathname);
}, [location.pathname, setServerState]);

useEffect(() => {
Expand Down
37 changes: 24 additions & 13 deletions packages/hydrogen/src/framework/docs/react-server-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ Due to these constraints, there are [specific rules](https://github.com/josephsa

![A diagram that illustrates the rules that apply to server and client components](/assets/custom-storefronts/hydrogen/server-client-component-rules.png)


### Example

The following example shows a server component (`Product.server.jsx`) that uses the [`useShopQuery`](/api/hydrogen/hooks/global/useshopquery) hook to fetch data. The data is passed to a client component (`WishListButton.client.jsx`) that uses state:

{% codeblock file, filename: 'Product.server.jsx' %}

```js
import {useShopQuery} from '@shopify/hydrogen';
import WishListButton from './WishListButton.client';
Expand All @@ -40,10 +40,11 @@ export default function Product() {
);
}
```
{% endcodeblock %}

{% endcodeblock %}

{% codeblock file, filename: 'WishListButton.client.jsx' %}

```js
import {useState} from 'react';

Expand All @@ -57,8 +58,8 @@ export default function WishListButton({product}) {
);
}
```
{% endcodeblock %}

{% endcodeblock %}

### Sharing code between server and client

Expand Down Expand Up @@ -92,6 +93,7 @@ The following rules apply to `Provider` components:
The following example shows the implementation of a `Provider` component:

{% codeblock file, filename: 'CartContext.client.jsx' %}

```js
// Note: This must be a separate client component from your special Provider component.

Expand All @@ -109,11 +111,12 @@ export function useCartContext() {
return context;
}
```

{% endcodeblock %}

{% codeblock file, filename: 'CartProvider.client.jsx' %}
```js

```js
import {CartContext} from './CartContext.client';

export default function CartProvider({items, children}) {
Expand All @@ -125,11 +128,12 @@ export default function CartProvider({items, children}) {
return <CartContext.Provider value={value}>{children}</CartContext.Provider>;
}
```

{% endcodeblock %}

{% codeblock file, filename: 'App.server.jsx' %}
```js

```js
import CartProvider from './CartProvider.client';

export default function App() {
Expand All @@ -142,6 +146,7 @@ export default function App() {
);
}
```

{% endcodeblock %}

## Working with React Server Components
Expand All @@ -158,19 +163,21 @@ Sharing state information between the client and server is important for common

1. `App.server.jsx` relies on the `page` state to choose the correct route to render. To change routes, the client updates the `page` state:

{% codeblock file, filename: 'ProductDetails.client.jsx' %}
```js
useEffect(() => {
setServerState('page', location.pathname);
}, [location.pathname, setServerState]);
```
{% endcodeblock %}
{% codeblock file, filename: 'ProductDetails.client.jsx' %}

```js
useEffect(() => {
setServerState('pathname', location.pathname);
}, [location.pathname, setServerState]);
```

{% endcodeblock %}

2. The `page` state is sent to the server. This happens through a `useServerResponse` fetch call. It's a special server endpoint called `/react` which accepts `state` as a query parameter.
3. The `/react` endpoint returns the wire representation for the new state.
4. The state is partially hydrated (made interactive) and rendered into the DOM, similar to how the initial page was made interactive.
Hydrogen uses `/react` for routing, but also for any other state that needs to be synced to the server.
Hydrogen uses `/react` for routing, but also for any other state that needs to be synced to the server.
### Fetching data on the server
Expand All @@ -194,21 +201,25 @@ When you send props to client components from a server component, make sure that
The following prop would send successfully:

{% codeblock file, filename: 'App.server.jsx' %}

```jsx
<MyClientComponent color="red" intro={<p>Here's my favorite color:</p>}>
Great to have you here today.
</MyClientComponent>
```

{% endcodeblock %}

The following prop wouldn't send successfully:
{% codeblock file, filename: 'App.server.jsx' %}
```jsx
<MyClientComponent onClick={() => console.log('uh oh')}>
Great to have you here today.
</MyClientComponent>
```
{% endcodeblock %}
## Next steps
Expand Down

0 comments on commit 53c1110

Please sign in to comment.