简体   繁体   English

在服务器端渲染(节点/ Express)中反应Cookie

[英]React Cookies in Server Side Rendering (Node/Express)

I have a React server side rendered web application. 我有一个React服务器端渲染的Web应用程序。

When the user requests "myapp.com/data" I have a Node Express wildcard route set up to catch that request. 当用户请求“ myapp.com/data”时,我将设置一个Node Express通配符路由来捕获该请求。 Inside that route handler, I create a Redux store for the server and then render 在该路由处理程序内,我为服务器创建一个Redux存储,然后进行渲染

app.get("/*", (req, res) => {
const content = renderToString(
    <Provider store={store}>
      <StaticRouter location={req.path} context={{}}>
        <Routes />
      </StaticRouter>
    </Provider>
  );
// send a bunch of HTML to client with {content} inside the React root div
}

Obviously I have client side code to hydrate the content. 显然,我有客户端代码来混合内容。 I create a different store for the client side, but I don't think that's relevant to the question. 我为客户端创建了另一个商店,但是我认为这与问题无关。

const store = createStore(
  reducers,
  {},
  composeEnhancers(applyMiddleware(thunk))
);

const jsx = (
  <Provider store={store}>
    <BrowserRouter>
      <Routes />
    </BrowserRouter>
  </Provider>
);

ReactDOM.hydrate(jsx, document.querySelector("#react-root"));

I have a service set up to do all the fetching and setting of the cookie, using "universal-cookie". 我设置了一项服务,以使用“通用cookie”来完成cookie的所有获取和设置。

import Cookie from "universal-cookie";
...
...
login(args) {
    const cookie = new Cookie();
    return new Promise((resolve, reject) => {
      fetch(`${apiURLs.login}`, {
        method: "post",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(args)
      })
        .then(response => {
          if (response.status !== 200)
            throw { status: response.status, message: response.message };
          return response.json();
        })
        .then(json => {
          cookie.set("authToken", json.authToken);
          resolve(json);
        })
        .catch(error => {
          reject(error);
        });
    });
  }

This all works fine. 这一切都很好。

Inside my client side code, I've created a component. 在我的客户端代码中,我创建了一个组件。

import Cookie from "universal-cookie";
...
...
const PrivateRoute = ({ component: Component, ...rest }) => {
  const cookie = new Cookie();
  const authToken = cookie.get("authToken");
  console.log("Auth Token inside <PrivateRoute /> = ");
  console.log(authToken);
  return (
    <Route
      {...rest}
      render={props => {
        return AuthService.checkToken("authToken").then(response => {
          return response.success;
        }) === true ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: "/login",
              state: {
                referrer: props.location
              }
            }}
          />
        );
      }}
    />
  );
};

THE PROBLEM (tl;dr): 问题(tl; dr):

const authToken = cookie.get("authToken");
console.log("Auth Token inside <PrivateRoute /> = ");
console.log(authToken);

Inside my PrivateRoute component, the auth token logs 'undefined' on the server-generated code and returns the correct value on the client side. 在我的PrivateRoute组件内部,身份验证令牌在服务器生成的代码上记录“未定义” ,并在客户端返回正确的值。

How universal-cookie lib gets the cookies? universal-cookie库如何获取cookie? From the docs, you need to pass it the cookie header to the constructor. 从文档中,您需要将cookie标头传递给构造函数。

// Server Example
import Cookies from 'universal-cookie';

const cookies = new Cookies(req.headers.cookie);

console.log(cookies.get('myCat')); // Pacman or undefined if not set yet

I would suggest you to refactor this code so your component won't know the source of the data (cookie). 我建议您重构此代码,以便您的组件不知道数据(cookie)的来源。

One common option is to put it on the redux store when ever you create the store (can be on the initial store as well). 一种常见的选择是在创建商店时将其放置在redux商店中(也可以在初始商店中)。

With this approach you will need to read the cookie on client-side (when initialising the store in this case read the cookie from document.cookie) & in server-side (when initialising the store, in this case read it from request object). 使用这种方法,您将需要在客户端(在这种情况下初始化存储时,从document.cookie中读取cookie)和在服务器端(当初始化存储时,在这种情况下,从请求对象中读取)读取cookie。 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM