Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix server state to use pathname #130

Merged
merged 1 commit into from
Nov 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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