react-dom/server#renderToString JavaScript Examples

The following examples show how to use react-dom/server#renderToString. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: server.js    From ReactCookbook-source with MIT License 6 votes vote down vote up
server
  .disable('x-powered-by')
  .use(express.static(process.env.RAZZLE_PUBLIC_DIR))
  .get('/*', (req, res) => {
    const context = {};
    const markup = renderToString(
      <StaticRouter context={context} location={req.url}>
        <App />
      </StaticRouter>
    );

    if (context.url) {
      res.redirect(context.url);
    } else {
      res.status(200).send(
        `<!doctype html>
    <html lang="">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta charset="utf-8" />
        <title>Welcome to Razzle</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        ${cssLinksFromAssets(assets, 'client')}
    </head>
    <body>
        <div id="root">${markup}</div>
        ${jsScriptTagsFromAssets(assets, 'client', ' defer crossorigin')}
    </body>
</html>`
      );
    }
  });
Example #2
Source File: server.js    From merkur with MIT License 6 votes vote down vote up
export function createWidget(widgetParams) {
  return createMerkurWidget({
    ...widgetProperties,
    ...widgetParams,
    $dependencies: {
      render: renderToString,
    },
    async mount(widget) {
      const { View, slot = {} } = await viewFactory(widget);

      return {
        html: widget.$dependencies.render(View(widget)),
        slot: Object.keys(slot).reduce((acc, cur) => {
          acc[cur] = {
            name: slot[cur].name,
            html: widget.$dependencies.render(slot[cur].View(widget)),
          };

          return acc;
        }, {}),
      };
    },
  });
}
Example #3
Source File: RoutePublic.spec.js    From full-stack-fastapi-react-postgres-boilerplate with MIT License 6 votes vote down vote up
describe('modules/RoutePublic', () => {
  it('should render the Login component for unauthenticated access', () => {
    const render = renderToString(
      <Router initialEntries={['/login']}>
        <RoutePublic
          exact
          path="/login"
          component={() => <div>LOGIN</div>}
          isAuthenticated={false}
        />
      </Router>,
    );

    expect(render).toMatchSnapshot();
  });

  it('should redirect to /private for authenticated access', () => {
    const render = renderToString(
      <Router initialEntries={['/login']}>
        <RoutePublic
          exact
          path="/login"
          component={() => <div>LOGIN</div>}
          isAuthenticated={true}
        />
      </Router>,
    );

    expect(render).toMatchSnapshot();
  });
});
Example #4
Source File: RoutePrivate.spec.js    From full-stack-fastapi-react-postgres-boilerplate with MIT License 6 votes vote down vote up
describe('modules/RoutePrivate', () => {
  it('should redirect for unauthenticated access', () => {
    const render = renderToString(
      <Router initialEntries={['/private']}>
        <RoutePrivate
          exact
          path="/private"
          component={() => <div>PRIVATE</div>}
          isAuthenticated={false}
        />
      </Router>,
    );

    expect(render).toMatchSnapshot();
  });

  it('should allow navigation for authenticated access', () => {
    const render = renderToString(
      <Router initialEntries={['/private']}>
        <RoutePrivate
          exact
          path="/private"
          component={() => <div>PRIVATE</div>}
          isAuthenticated={true}
        />
      </Router>,
    );

    expect(render).toMatchSnapshot();
  });
});
Example #5
Source File: RoutePublic.spec.js    From full-stack-fastapi-react-postgres-boilerplate with MIT License 6 votes vote down vote up
describe('RoutePublic', () => {
  it('should render the Login component for unauthenticated access', () => {
    const render = renderToString(
      <Router initialEntries={['/login']}>
        <RoutePublic
          exact
          path="/login"
          component={() => <div>LOGIN</div>}
          isAuthenticated={false}
        />
      </Router>,
    );

    expect(render).toMatchSnapshot();
  });

  it('should redirect to /private for authenticated access', () => {
    const render = renderToString(
      <Router initialEntries={['/login']}>
        <RoutePublic
          exact
          path="/login"
          component={() => <div>LOGIN</div>}
          isAuthenticated={true}
        />
      </Router>,
    );

    expect(render).toMatchSnapshot();
  });
});
Example #6
Source File: RoutePrivate.spec.js    From full-stack-fastapi-react-postgres-boilerplate with MIT License 6 votes vote down vote up
describe('RoutePrivate', () => {
  it('should redirect for unauthenticated access', () => {
    const render = renderToString(
      <Router initialEntries={['/private']}>
        <RoutePrivate
          exact
          path="/private"
          component={() => <div>PRIVATE</div>}
          isAuthenticated={false}
        />
      </Router>,
    );

    expect(render).toMatchSnapshot();
  });

  it('should allow navigation for authenticated access', () => {
    const render = renderToString(
      <Router initialEntries={['/private']}>
        <RoutePrivate
          exact
          path="/private"
          component={() => <div>PRIVATE</div>}
          isAuthenticated={true}
        />
      </Router>,
    );

    expect(render).toMatchSnapshot();
  });
});
Example #7
Source File: server.jsx    From react-enterprise-starter-kit with MIT License 6 votes vote down vote up
server.get('/', (req, res) => {
  console.log('Middle Ware Called');
  console.log(path.resolve('./dist/index.html'));
  const data = fs.readFileSync(path.resolve('./dist/index.html'), 'utf8');
  const content = renderToString(
    <Provider store={store}>
      <App />
    </Provider>,
  );
  const preloadedState = `<script type="text/javascript" charset="utf-8"> window.__PRELOADED__STATE__ = ${JSON.stringify(store)} </script>`;
  const serverRenderedHTML = data.replace(
    '<div id="root"></div>',
    `<div id="root">${content}</div>${preloadedState}`,
  );

  res.status(200).send(serverRenderedHTML);
  // store.runSaga(rootSagas).toPromise()
  //   .then(() => {
  //     console.log('Saga Run Successfully');
  //     // res.status(200).send(serverRenderedHTML);
  //   })
  //   .catch((e) => {
  //     console.log('Saga Run Failed', e.message);
  //     // res.status(500).send(e.message);
  //   });
});
Example #8
Source File: ssr.js    From ReactCookbook-source with MIT License 6 votes vote down vote up
app.use('*', async (req, res) => {
    let componentData = {};

    let indexHTML = fs.readFileSync(path.resolve(__dirname, '../build/index.html'), {
        encoding: 'utf8',
    });

    let appHTML = renderToString(
        <StaticRouter location={req.originalUrl} context={componentData}>
            <App/>
        </StaticRouter>
    );

    indexHTML = indexHTML.replace('<div id="root"></div>', `<div id="app">${appHTML}</div>`);

    indexHTML = indexHTML.replace(
        'var initial_state = null;',
        `var initial_state = ${JSON.stringify(componentData)};`
    );

    // set header and status
    res.contentType('text/html');
    res.status(200);

    return res.send(indexHTML);
});
Example #9
Source File: ssr-handler.js    From divar-starter-kit with MIT License 6 votes vote down vote up
function getPageMarkup({
  store, context, preloadedData, location,
}) {
  const { Provider: InitialSSRDataProvider } = createNewContext();

  return renderToString(
    <Provider store={store}>
      <InitialSSRDataProvider value={initSSRContextValue(preloadedData)}>
        <StaticRouter context={context} location={location}>
          <AppRouter />
        </StaticRouter>
      </InitialSSRDataProvider>
    </Provider>,
  );
}
Example #10
Source File: index.js    From citr-v6-project with Apache License 2.0 6 votes vote down vote up
app.use((req, res) => {
  const staticContext = {};
  const reactMarkup = (
    <StaticRouter url={req.url} context={staticContext}>
      <App />
    </StaticRouter>
  );

  res.status(staticContext.statusCode || 200);
  res.send(`${parts[0]}${renderToString(reactMarkup)}${parts[1]}`);
  res.end();
});
Example #11
Source File: SSR.test.js    From react-menu with MIT License 6 votes vote down vote up
describe('Server rendering', () => {
  test('portal is not provided', () => {
    expect(renderToString(getMenu())).toContain(
      '</button><div class="szh-menu-container" style="position:relative"><ul role="menu"'
    );
  });

  test('portal is true', () => {
    expect(renderToString(getMenu({ portal: true }))).toContain(
      '</button><div class="szh-menu-container" style="position:relative"><ul role="menu"'
    );
  });

  test('portal.target is null', () => {
    expect(renderToString(getMenu({ portal: { target: null } }))).toContain(
      '</button><div class="szh-menu-container" style="position:relative"><ul role="menu"'
    );
  });

  test('portal.stablePosition is true', () => {
    expect(renderToString(getMenu({ portal: { stablePosition: true } }))).toContain(
      '</button></main>'
    );
  });
});
Example #12
Source File: server.js    From Learning-Redux with MIT License 6 votes vote down vote up
handleRender = (req, res) => {
  // Query our mock API asynchronously
  fetchCounter((apiResult) => {
    // Read the counter from the request, if provided
    const params = qs.parse(req.query)
    const counter = parseInt(params.counter, 10) || apiResult || 0

    // Compile an initial state
    const preloadedState = { counter }

    // Create a new Redux store instance
    const store = configureStore(preloadedState)

    // Render the component to a string
    const html = renderToString(
      <Provider store={store}>
        <App />
      </Provider>
    )

    // Grab the initial state from our Redux store
    const finalState = store.getState()

    // Send the rendered page back to the client
    res.send(renderFullPage(html, finalState))
  })
}
Example #13
Source File: entry.server.jsx    From redis-examples with MIT License 6 votes vote down vote up
export default function handleRequest(
  request,
  responseStatusCode,
  responseHeaders,
  remixContext
) {
  const markup = renderToString(
    <RemixServer context={remixContext} url={request.url} />
  );

  responseHeaders.set("Content-Type", "text/html");

  return new Response("<!DOCTYPE html>" + markup, {
    status: responseStatusCode,
    headers: responseHeaders,
  });
}
Example #14
Source File: server.js    From Learning-Redux with MIT License 6 votes vote down vote up
handleRender = (req, res) => {
  // Query our mock API asynchronously
  fetchCounter((apiResult) => {
    // Read the counter from the request, if provided
    const params = qs.parse(req.query);
    const counter = parseInt(params.counter, 10) || apiResult || 0;

    // Compile an initial state
    const preloadedState = { counter };

    // Create a new Redux store instance
    const store = configureStore(preloadedState);

    // Render the component to a string
    const html = renderToString(
      <Provider store={store}>
        <App />
      </Provider>
    );

    // Grab the initial state from our Redux store
    const finalState = store.getState();

    // Send the rendered page back to the client
    res.send(renderFullPage(html, finalState));
  });
}
Example #15
Source File: entry-server.jsx    From reactplate with MIT License 5 votes vote down vote up
export function render(url, context) {
  return renderToString(
    <StaticRouter location={url} context={context}>
      <App />
    </StaticRouter>
  );
}
Example #16
Source File: test.js    From react-instagram-zoom-slider with MIT License 5 votes vote down vote up
describe('Server-side rendering', () => {
  it('renders on a server without crashing', () => {
    const slides = [<img src="..." alt="First slide" />, <img src="..." alt="Second slide" />]
    const renderOnServer = () => renderToString(<Slider initialSlide={1} slides={slides} />)

    expect(renderOnServer).not.toThrow()
  })
})
Example #17
Source File: server.js    From react-keycloak-examples with MIT License 5 votes vote down vote up
server
  .disable('x-powered-by')
  .use(express.static(process.env.RAZZLE_PUBLIC_DIR))
  .use(cookieParser()) // 1. Add cookieParser Express middleware
  .get('/*', (req, res) => {
    const context = {}

    // 2. Create an instance of ServerPersistors.ExpressCookies passing the current request
    const cookiePersistor = ServerPersistors.ExpressCookies(req)

    // 3. Wrap the App inside SSRKeycloakProvider
    const markup = renderToString(
      <SSRKeycloakProvider
        keycloakConfig={getKeycloakConfig()}
        persistor={cookiePersistor}
      >
        <StaticRouter context={context} location={req.url}>
          <App />
        </StaticRouter>
      </SSRKeycloakProvider>
    )

    if (context.url) {
      res.redirect(context.url)
    } else {
      res.status(200).send(
        `<!doctype html>
    <html lang="">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta charset="utf-8" />
        <title>Welcome to Razzle</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script>window.env = ${JSON.stringify(getKeycloakConfig())}</script>
        ${
          assets.client.css
            ? `<link rel="stylesheet" href="${assets.client.css}">`
            : ''
        }
        ${
          process.env.NODE_ENV === 'production'
            ? `<script src="${assets.client.js}" defer></script>`
            : `<script src="${assets.client.js}" defer crossorigin></script>`
        }
    </head>
    <body>
        <div id="root">${markup}</div>
    </body>
</html>`
      )
    }
  })
Example #18
Source File: server.js    From module-federation-examples with MIT License 5 votes vote down vote up
app.get('*', (req, res, next) => {
  const html = renderToString(<App />);
  res.send(html);
});
Example #19
Source File: render.js    From tunnel-tool with MIT License 5 votes vote down vote up
render = (
  {
    App,
    paths: { resources: RESOURCES_BASE_ROUTE, base: BASE_ROUTE },
    urls: {
      external: { graphql: EXTERNAL_URL_GRAPH, events: EXTERNAL_URL_EVENTS },
      internal: { graphql: INTERNAL_URL_GRAPH, events: INTERNAL_URL_EVENTS }
    },
    watchers,
    reducers,
    req,
    res
  },
  cxt
) => {
  let routerContext = {};
  const { store } = configureStore({ reducers, initState: {} });
  const { graph } = configureGraph({
    url: INTERNAL_URL_GRAPH,
    req,
    initState: {}
  });

  const AppRoot = (
    <ApolloProvider client={graph}>
      <Provider store={store}>
        <StaticRouter location={req.url} context={routerContext}>
          <App />
        </StaticRouter>
      </Provider>
    </ApolloProvider>
  );

  getDataFromTree(AppRoot)
    .then(() => {
      const preloadedState = store.getState();
      const htmlSteam =
        Template.header({
          paths: { base: BASE_ROUTE, resources: RESOURCES_BASE_ROUTE }
        }) +
        renderToString(AppRoot) +
        Template.footer({
          config: {
            paths: { base: BASE_ROUTE, resources: RESOURCES_BASE_ROUTE },
            urls: {
              graphql: EXTERNAL_URL_GRAPH,
              events: EXTERNAL_URL_EVENTS
            }
          },
          preloadedState,
          preloadedGraphState: graph.extract()
        });

      if (routerContext.url) {
        res.redirect(routerContext.url);
      } else {
        res.status(200);
        res.send(htmlSteam);
      }
    })
    .catch(function(error) {
      console.log(error);
    });
}
Example #20
Source File: server.js    From react-workshop with MIT License 5 votes vote down vote up
server
  .disable('x-powered-by')
  .use(express.static(process.env.RAZZLE_PUBLIC_DIR))
  .get('/*', (req, res) => {
    const apolloClient = new ApolloClient({
      ssrMode: true,
      cache: new InMemoryCache(),
      link: createHttpLink({
        uri: 'https://asia-southeast2-minitokopedia.cloudfunctions.net/graphql',
      }),
    });

    const context = {};
    const markup = (
      <ApolloProvider client={apolloClient}>
        <StaticRouter context={context} location={req.url}>
          <App />
        </StaticRouter>
      </ApolloProvider>
    );

    if (context.url) {
      res.redirect(context.url);
    } else {
      getDataFromTree(markup).then((content) => {
        const initialState = apolloClient.extract();

        const html = renderToString(
          <html lang="en">
            <head>
              <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
              <meta charset="utf-8" />
              <title>Welcome to Razzle</title>
              <meta name="viewport" content="width=device-width, initial-scale=1" />
              {cssLinksFromAssets(razzleAssets, 'client')}
            </head>
            <body>
              <div id="root" dangerouslySetInnerHTML={{ __html: content }} />
              <script
                dangerouslySetInnerHTML={{
                  __html: `window.__APOLLO_STATE__=${JSON.stringify(initialState).replace(/</g, '\\u003c')};`,
                }}
              />
              {jsScriptTagsFromAssets(razzleAssets, 'client')}
            </body>
          </html>,
        );

        res.status(200).header('Content-Type', 'text/html').send(`<!doctype html>\n${html}`);
      });
    }
  });
Example #21
Source File: render.js    From ReactSourceCodeAnalyze with MIT License 5 votes vote down vote up
export default function render() {
  var html = renderToString(<App assets={assets} />);
  // There's no way to render a doctype in React so prepend manually.
  // Also append a bootstrap script tag.
  return '<!DOCTYPE html>' + html;
}
Example #22
Source File: MapView.jsx    From resilience-app with GNU General Public License v3.0 5 votes vote down vote up
function MissionMarker({ currentUid, groups, mission, setSelectedMission, volunteers }) {
  const classes = useStyles();
  const [anchorEl, setAnchorEl] = React.useState(null);
  let html = `<div class='${clsx(
    classes.markerPin,
    currentUid === mission.uid && classes.currentMarker
  )}'></div>`;

  let color = "black";

  if (mission.groupDisplayName) {
    color = _.randomColor(mission.groupDisplayName);
    const GroupIconHtml = renderToString(
      <GroupWorkIcon className={classes.customGroupIcon} style={{ color: color }} />
    );
    html += GroupIconHtml;
  }

  const FoodboxIconHtml = renderToString(<FoodBoxIcon className={classes.innerFoodBoxMarker} />);
  html += FoodboxIconHtml;

  const CustomIcon = new DivIcon({
    className: clsx(classes.customDivIcon),
    html: html,
    iconSize: [30, 42],
    iconAnchor: [15, 42], // half of width + height
  });

  return (
    <Marker
      icon={CustomIcon}
      key={mission.uid}
      position={mission.deliveryLocation}
      onClick={(event) => {
        setAnchorEl(event.target.getElement());
        setSelectedMission(mission.uid);
      }}
    >
      <Popup className={classes.popup} autoClose={true}>
        <Grid container>
          <Grid container item xs>
            {mission.groupDisplayName}
            {mission.details?.map((box, index) => {
              return (
                <div key={index}>
                  {box.quantity} x {box.displayName}
                </div>
              );
            })}
          </Grid>
          <Grid item>
            <MissionItemMenu
              groups={groups}
              mission={mission}
              volunteers={volunteers}
              boxRef={{ current: anchorEl }}
            />
          </Grid>
        </Grid>
      </Popup>
    </Marker>
  );
}
Example #23
Source File: render.js    From Learning-Redux with MIT License 5 votes vote down vote up
serverSideRendering = (indexFile, loadStaticFile) => (req, res) => {
  const isIndexPage = req.url === "/" || req.url === "/index.html";
  if (isIndexPage) {
    if (cachedResult) return res.send(cachedResult);
  }

  console.log("server-side rendering started for", req.url);

  const history = createHistory();

  const store = configureStore({}, history, true);
  return initStore(store)
    .then(() => {
      const context = {};
      const markup = renderToString(
        <Provider store={store}>
          <StaticRouter
            location={isIndexPage ? "/" : req.url}
            context={context}
          >
            <App />
          </StaticRouter>
        </Provider>
      );

      const storeState = JSON.stringify(store.getState()).replace(
        /</g,
        "\\u003c"
      );

      const dom = new JSDOM(indexFile, { runScripts: "outside-only" });
      dom.window.eval(`
        document.getElementById('root').innerHTML = '${markup}'
      `);
      dom.window.eval(`
        var script = document.createElement('script')
        script.innerHTML = 'window.__PRELOADED_STATE__ = ${storeState}'
        document.body.insertBefore(script,
          document.getElementsByTagName('script')[0]
        )
      `);

      if (isIndexPage) {
        cachedResult = dom.serialize();
        console.log("server-side rendering done, cached result");
        if (res) return res.send(cachedResult);
      } else {
        console.log("server-side rendering done");
        if (res) return res.send(dom.serialize());
      }
    })
    .catch((err) => {
      console.error("server-side rendering error:", err);
      if (loadStaticFile) return loadStaticFile(req, res);
    });
}
Example #24
Source File: server.js    From Edlib with GNU General Public License v3.0 4 votes vote down vote up
renderApp = async (req, res) => {
    const context = {};
    const emotionCache = createEmotionCache();
    const sheet = new ServerStyleSheet();

    const emotionServers = [
        // Every emotion cache used in the app should be provided.
        // Caches for MUI should use "prepend": true.
        // MUI cache should come first.
        emotionCache,
        getTssDefaultEmotionCache({ doReset: true }),
    ].map(createEmotionServer);

    const wwwUrl = `${req.protocol}://${req.get('host')}`;

    const SetupApp = (initialState, promiseList = []) => (
        <CacheProvider value={emotionCache}>
            <ThemeProvider theme={muiTheme}>
                <StaticRouter context={context} location={req.url}>
                    <FetchProvider
                        promiseList={promiseList}
                        initialState={initialState}
                        ssrCookies={res.getCookies()}
                        ssrAddCookiesFromSetCookie={res.addCookiesFromSetCookie}
                    >
                        <ConfigurationProvider
                            apiUrl={wwwUrl.replace('www', 'api')}
                            wwwUrl={wwwUrl}
                            isSSR
                            cookies={req.cookies}
                        >
                            <App />
                        </ConfigurationProvider>
                    </FetchProvider>
                </StaticRouter>
            </ThemeProvider>
        </CacheProvider>
    );

    const maxDepth = 10;
    const getStateFromTree = async (state = {}, depth = 0) => {
        const promiseList = [];
        renderToString(SetupApp(state, promiseList));
        if (promiseList.length !== 0 && depth < maxDepth) {
            await addPromiseListToState(state, promiseList);

            return getStateFromTree(state, depth + 1);
        }

        return { state };
    };

    const { state } = await getStateFromTree();

    const markup = renderToString(sheet.collectStyles(SetupApp(state, [])));
    const helmet = Helmet.renderStatic();

    // Grab the CSS from emotion
    const styleTagsAsStr = emotionServers
        .map(({ extractCriticalToChunks, constructStyleTagsFromChunks }) =>
            constructStyleTagsFromChunks(extractCriticalToChunks(markup))
        )
        .join('');

    // Grab the CSS from styled-components
    const styledComponentsTags = sheet.getStyleTags();

    const html = `<!doctype html>
    <html lang="">
    <head ${helmet.htmlAttributes.toString()}>
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1">
        ${cssLinksFromAssets(assets, 'client')}
        ${styleTagsAsStr}
        ${styledComponentsTags}
        ${helmet.title.toString()}
        ${helmet.meta.toString()}
        ${helmet.link.toString()}
    </head>
    <body ${helmet.bodyAttributes.toString()}>
        <script>
            window.__FETCH_STATE__=${JSON.stringify(state).replace(
                /</g,
                '\\u003c'
            )};
        </script>
        <div id="root">${markup}</div>
        ${jsScriptTagsFromAssets(assets, 'client', 'defer', 'crossorigin')}
    </body>
    </html>`;

    return { context, html };
}
Example #25
Source File: server-rendering.spec.js    From Learning-Redux with MIT License 4 votes vote down vote up
describe('React', () => {
  describe('server rendering', () => {
    function greetingReducer(state = { greeting: 'Hello' }, action) {
      return action && action.payload ? action.payload : state
    }

    const Greeting = ({ greeting, greeted }) => greeting + ' ' + greeted
    const ConnectedGreeting = connect((state) => state)(Greeting)

    const Greeter = (props) => (
      <div>
        <ConnectedGreeting {...props} />
      </div>
    )

    class Dispatcher extends React.Component {
      constructor(props) {
        super(props)
        if (props.constructAction) {
          props.dispatch(props.constructAction)
        }
      }
      UNSAFE_componentWillMount() {
        if (this.props.willMountAction) {
          this.props.dispatch(this.props.willMountAction)
        }
      }
      render() {
        if (this.props.renderAction) {
          this.props.dispatch(this.props.renderAction)
        }

        return <Greeter greeted={this.props.greeted} />
      }
    }
    const ConnectedDispatcher = connect()(Dispatcher)

    it('should be able to render connected component with props and state from store', () => {
      const store = createStore(greetingReducer)

      const markup = renderToString(
        <Provider store={store}>
          <Greeter greeted="world" />
        </Provider>
      )

      expect(markup).toContain('Hello world')
    })

    it('should run in an SSR environment without logging warnings about useLayoutEffect', () => {
      const store = createStore(greetingReducer)

      const spy = jest.spyOn(console, 'error').mockImplementation(() => {})

      const markup = renderToString(
        <Provider store={store}>
          <Greeter greeted="world" />
        </Provider>
      )

      expect(spy).toHaveBeenCalledTimes(0)

      spy.mockRestore()
    })

    it('should render with updated state if actions are dispatched before render', () => {
      const store = createStore(greetingReducer)

      store.dispatch({ type: 'Update', payload: { greeting: 'Hi' } })

      const markup = renderToString(
        <Provider store={store}>
          <Greeter greeted="world" />
        </Provider>
      )

      expect(markup).toContain('Hi world')
      expect(store.getState().greeting).toContain('Hi')
    })

    it('should render children with updated state if actions are dispatched in ancestor', () => {
      /*
          Dispatching during construct, render or willMount is
          almost always a bug with SSR (or otherwise)

          This behaviour is undocumented and is likely to change between
          implementations, this test only verifies current behaviour

          Note: this test fails in v6, because we use context to propagate the store state, and the entire
          tree will see the same state during the render pass.
          In all other versions, including v7, the store state may change as actions are dispatched
          during lifecycle methods, and components will see that new state immediately as they read it.
      */
      const store = createStore(greetingReducer)

      const constructAction = { type: 'Update', payload: { greeting: 'Hi' } }
      const willMountAction = { type: 'Update', payload: { greeting: 'Hiya' } }
      const renderAction = { type: 'Update', payload: { greeting: 'Hey' } }

      const markup = renderToString(
        <Provider store={store}>
          <ConnectedDispatcher
            constructAction={constructAction}
            greeted="world"
          />
          <ConnectedDispatcher
            willMountAction={willMountAction}
            greeted="world"
          />
          <ConnectedDispatcher renderAction={renderAction} greeted="world" />
        </Provider>
      )

      expect(markup).toContain('Hi world')
      expect(markup).toContain('Hiya world')
      expect(markup).toContain('Hey world')
      expect(store.getState().greeting).toContain('Hey')
    })

    it('should render children with changed state if actions are dispatched in ancestor and new Provider wraps children', () => {
      /*
          Dispatching during construct, render or willMount is
          almost always a bug with SSR (or otherwise)

          This behaviour is undocumented and is likely to change between
          implementations, this test only verifies current behaviour

          This test works both when state is fetched directly in connected
          components and when it is fetched in a Provider and placed on context
      */
      const store = createStore(greetingReducer)

      const constructAction = { type: 'Update', payload: { greeting: 'Hi' } }
      const willMountAction = { type: 'Update', payload: { greeting: 'Hiya' } }
      const renderAction = { type: 'Update', payload: { greeting: 'Hey' } }

      const markup = renderToString(
        <Provider store={store}>
          <ConnectedDispatcher
            constructAction={constructAction}
            greeted="world"
          />
          <ConnectedDispatcher
            willMountAction={willMountAction}
            greeted="world"
          />
          <ConnectedDispatcher renderAction={renderAction} greeted="world" />
        </Provider>
      )

      expect(markup).toContain('Hi world')
      expect(markup).toContain('Hiya world')
      expect(markup).toContain('Hey world')
      expect(store.getState().greeting).toContain('Hey')
    })
  })
})
Example #26
Source File: server.js    From littlelink-server with MIT License 4 votes vote down vote up
server
  .disable('x-powered-by')
  .use(express.static(process.env.RAZZLE_PUBLIC_DIR))
  .get('/', (req, res) => {
    const context = {};
    const markup = renderToString(
      <StaticRouter context={context} location={req.url}>
        <App />
      </StaticRouter>,
    );

    if (context.url) {
      res.redirect(context.url);
    } else {
      res.status(200).send(
        `<!doctype html>
    <html lang="${runtimeConfig.LANG || 'en'}">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta charset="utf-8" />
        <title >${runtimeConfig.META_TITLE}</title>
        <meta name="description" content="${runtimeConfig.META_DESCRIPTION}">
        <meta name="author" content="${runtimeConfig.META_AUTHOR}">
        <meta name="keywords" content="${runtimeConfig.META_KEYWORDS}">
        <meta name="robots" content="${
          runtimeConfig.META_INDEX_STATUS || 'noindex'
        }">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        ${
          runtimeConfig.OG_SITE_NAME
            ? `<meta property="og:site_name" content="${runtimeConfig.OG_SITE_NAME}" />`
            : ''
        }
        ${
          runtimeConfig.OG_TITLE
            ? `<meta property="og:title" content="${runtimeConfig.OG_TITLE}" />`
            : ''
        }
        ${
          runtimeConfig.OG_DESCRIPTION
            ? `<meta property="og:description" content="${runtimeConfig.OG_DESCRIPTION}" />`
            : ''
        }
        ${
          runtimeConfig.OG_URL
            ? `<meta property="og:url" content="${runtimeConfig.OG_URL}" />`
            : ''
        }
        <meta property="og:type" content="siteweb" />
        ${
          runtimeConfig.OG_IMAGE
            ? `
                <meta property="og:image" content="${runtimeConfig.OG_IMAGE}" />
                <meta property="og:image:secure_url" content="${runtimeConfig.OG_IMAGE}" />
            `
            : ''
        }
        ${
          runtimeConfig.OG_IMAGE_WIDTH
            ? `<meta property="og:image:width" content="${runtimeConfig.OG_IMAGE_WIDTH}" />`
            : ''
        }
        ${
          runtimeConfig.OG_IMAGE_HEIGHT
            ? `<meta property="og:image:height" content="${runtimeConfig.OG_IMAGE_HEIGHT}" />`
            : ''
        }
        ${
          runtimeConfig.TWITTER_CARD
            ? `<meta property="twitter:card" content="${runtimeConfig.TWITTER_CARD}" />`
            : ''
        }
        ${
          runtimeConfig.TWITTER_IMAGE
            ? `<meta property="twitter:image" content="${runtimeConfig.TWITTER_IMAGE}" />`
            : ''
        }
        ${
          runtimeConfig.TWITTER_SITE
            ? `<meta property="twitter:site" content="${runtimeConfig.TWITTER_SITE}" />`
            : ''
        }
        ${
          runtimeConfig.TWITTER_CREATOR
            ? `<meta property="twitter:creator" content="${runtimeConfig.TWITTER_CREATOR}" />`
            : ''
        }
        <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,700,800&amp;display=swap" rel="stylesheet">
        <link rel="stylesheet" href="css/normalize.css">
        <link rel="stylesheet" href="css/${theme}">
        <link rel="stylesheet" href="css/brands.css">
        ${cssLinksFromAssets(assets, 'client')}
        <link rel="icon" type="image/png" href="${runtimeConfig.FAVICON_URL}">
        ${
          runtimeConfig.GA_TRACKING_ID
            ? `
            <!-- Global site tag (gtag.js) - Google Analytics -->
            <script async src="https://www.googletagmanager.com/gtag/js?id=${runtimeConfig.GA_TRACKING_ID}"></script>
            <script>
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());

        gtag('config', '${runtimeConfig.GA_TRACKING_ID}');
      </script>`
            : ''
        }
        ${
          runtimeConfig.UMAMI_WEBSITE_ID && runtimeConfig.UMAMI_APP_URL
            ? `
            <!-- Umami Analytics -->
            <script async defer data-website-id="${runtimeConfig.UMAMI_WEBSITE_ID}" src="${runtimeConfig.UMAMI_APP_URL}/umami.js">
            </script>`
            : ''
        }
        ${
          runtimeConfig.MATOMO_URL && runtimeConfig.MATOMO_SITE_ID
            ? `
            <!-- Matomo -->
            <script type="text/javascript">
                var _paq = window._paq || [];
                /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
                _paq.push(['trackPageView']);
                _paq.push(['enableLinkTracking']);
                (function () {
                    var u = "${runtimeConfig.MATOMO_URL}/";
                    _paq.push(['setTrackerUrl', u + 'matomo.php']);
                    _paq.push(['setSiteId', '${runtimeConfig.MATOMO_SITE_ID}']);
                    var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
                    g.type = 'text/javascript';
                    g.async = true;
                    g.defer = true;
                    g.src = u + 'matomo.js';
                    s.parentNode.insertBefore(g, s);
                })();
            </script>
            <!-- Matomo End -->`
            : ''
        }

    </head>
    <body>
        ${
          runtimeConfig.MATOMO_URL && runtimeConfig.MATOMO_SITE_ID
            ? `
            <!-- Matomo Image Tracker-->
            <img referrerpolicy="no-referrer-when-downgrade" src="${runtimeConfig.MATOMO_URL}/matomo.php?idsite=${runtimeConfig.MATOMO_SITE_ID}&amp;rec=1" style="border:0" alt="" />
            <!-- End Matomo -->`
            : ''
        }
        <div id="root">${markup}</div>
        <script>window.env = ${serialize(runtimeConfig)};</script>
        ${jsScriptTagsFromAssets(assets, 'client', ' defer crossorigin')}
    </body>
    </html>`,
      );
    }
  });
Example #27
Source File: load-routes.js    From crate with MIT License 4 votes vote down vote up
export default function (app) {
  console.info('SETUP - Load routes..')

  // Store (new store for each request)
  const store = createStore(
    rootReducer,
    applyMiddleware(thunk)
  )

  // Match any Route
  app.get('*', (request, response) => {

    // Check for auth
    if (request.cookies.auth) {
      const auth = JSON.parse(request.cookies.auth)

      if (auth && auth.token !== '' && auth.user) {
        store.dispatch(setUser(auth.token, auth.user))
      }
    }

    // HTTP status code
    let status = 200

    const matches = Object.values(routes).reduce((matches, route) => {
      const match = matchPath(request.url, typeof route.path === 'function' ? route.path() : route.path, route)

      if (match && match.isExact) {
        matches.push({
          route,
          match,
          promise: route.component.fetchData ? route.component.fetchData({
            store,
            params: match.params
          }) : Promise.resolve(null)
        })
      }
      return matches
    }, [])

    // No such route, send 404 status
    if (matches.length === 0) {
      status = 404
    }

    // Any AJAX calls inside components
    const promises = matches.map((match) => {
      return match.promise
    })

    // Resolve the AJAX calls and render
    Promise.all(promises)
      .then((...data) => {
        const initialState = store.getState()
        const context = {}

        const appHtml = renderToString(
          <Provider store={store} key="provider">
            <StaticRouter context={context} location={request.url}>
              <App/>
            </StaticRouter>
          </Provider>
        )

        if (context.url) {
          response.redirect(context.url)
        } else {
          // Get Meta header tags
          const helmet = Helmet.renderStatic()

          const styles = flushToHTML()

          const html = view(APP_URL, NODE_ENV, helmet, appHtml, styles, initialState)

          // Reset the state on server
          store.dispatch({
            type: 'RESET'
          })

          // Finally send generated HTML with initial data to the client
          return response.status(status).send(html)
        }
      })
      .catch(error => {
        console.error(error)
      })
  })

}