Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-ssr-fork

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-ssr-fork

React SSR Fork facilitates rendering different content on server and client side.

  • 1.0.1
  • latest
  • Source
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

React SSR Fork

React SSR Fork facilitates rendering different content on server and client side, and solves hydration mismatch issue.

Features

  • Provides <Client> component to render client side content, and <Server> for server side
  • Automatically solves the hydration issue of mismatched client and server side content
  • Prevents unecessary client side re-renders when solving hydration mismatch
  • Requires minimum setup and is easy to use.

Installation

Install the library:

npm install --save react-ssr-fork

Usage

Wrap your main application component inside <ForkProvider>. This component contains the business logic of solving hydration mismatch issue, also provides context for <Client> and <Server> components.

  1. Your client side entry might look like this (<ForkProvider> wrapping is obligatory):
// client.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { ForkProvider } from 'react-ssr-fork';
import App from 'your-components/App';

ReactDOM.hydrate(
  <ForkProvider>
    <App />    
  </ForkProvider>,
  document.getElementById('root')
);
  1. And your server side entry file could look this way (<ForkProvider> wrapping is obligatory):
// server.jsx
import React from 'react';
import { renderToString } from 'react-dom/server';
import { ForkProvider } from 'react-ssr-fork';
import App from 'your-components/App.jsx';

const content = renderToString(
  <ForkProvider>
    <App />
  </ForkProvider>
);
// ...
  1. Then use <Client> component to render specifically client side content, and respectively <Server> to render server side content. Your <App> component might look like this:
// App.jsx
import React from 'react';
import { Client, Server } from 'react-ssr-fork';

export default function App() {
  return (
    <div>
      <Client>
        I run on client
      </Client>
      <Server>
        I run on server
      </Server>
    </div>
  );
}

Here's what happens when you run the application:

  • On server side <App> simply renders <div>I run on server</div>
  • On client side during hydration <App> renders <div>I run on server</div> (to match the content sent from server), then right away re-renders to actual client content <div>I run on client</div>.

Requirements

  • On both client and server sides <Client> and <Server> must to be wrapped inside <ForkProvider>
  • Requires React 16.3 and above

Why not use this.state.isCient approach?

ReactDOM.hydrate() documentation suggests solving hydration mismatch warning using two-pass rendering and this.state.isClient flag. Here's a simple imlementation:

import React, { Component } from 'react';

class Message extends Component {
  state = { isClient: false }

  render() {
    return (
      <div>
        {this.state.isClient ? 'I run on server' : 'I run on client'}
      </div>
    );
  }

  componentDidMount() {
    this.setState({ isClient: true });
  }
}

ReactDOM.hydrate(
  <Message />,
  document.getElementById('root')
);

On client side during initial render (hydration) this.state.isClient is false. Thus <Message> outputs <div>I run on server</div>. This output matches the one sent from server side, and React doesn't throw any mismatch warnings during hydration.

Right away after mounting of <Message>, componentDidMount() method is invoked and this.state.isClient becomes true. As result <Message> renders <div>I run on client</div>.

As described above, solving hydration mismatch using two-pass rendering works.

But there is a drawback. If a new instance of <Message> is rendered on the client side on later stages, two-pass rendering will be applied even if that's unnecessary. This makes your component slower. That's the problem solved by React SSR Fork library, which prevents unnecessary two-pass rendering when this is not necessary.

Unit testing

React SSR Fork components faciliate unit testing of your components.

<ForkProvider> accepts a special boolean prop canUseDom meant to indicate manually the client or server environment in your unit tests. For example:

import React from 'react';
import { mount } from 'enzyme';

import { ForkProvider } from 'react-ssr-fork';

function App() {
  return (
    <div>
      <Client>
        I run on client
      </Client>
      <Server>
        I run on server
      </Server>
    </div>
  );
}

describe('<App>', function () {
  test('renders client content on client side', function () {
    const wrapper = mount(
      // Client environment: canUseDom=true
      <ForkProvider canUseDom={true}>
        <App />
      </ForkProvider>
    );
    expect(wrapper.contains('I run on client')).toBe(true);
    expect(wrapper.contains('I run on server')).toBe(false);
  });

  test('renders server content on server side', function () {
    const wrapper = mount(
      // Server environment: canUseDom=false
      <ForkProvider canUseDom={false}>
        <App />
      </ForkProvider>
    );
    expect(wrapper.contains('I run on client')).toBe(false);
    expect(wrapper.contains('I run on server')).toBe(true);
  });
});

License

Licensed under MIT

Keywords

FAQs

Package last updated on 10 Jul 2018

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc