Реагировать на файлы cookie при рендеринге на стороне сервера (Node / Express) - PullRequest
0 голосов
/ 15 апреля 2019

У меня есть отрендеренное веб-приложение на стороне сервера React.

Когда пользователь запрашивает «myapp.com/data», у меня установлен маршрутный символ Node Express, чтобы перехватить этот запрос. Внутри этого обработчика маршрута я создаю хранилище 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
}

Очевидно, у меня есть код на стороне клиента для увлажнения содержимого. Я создаю другой магазин для клиентской стороны, но я не думаю, что это имеет отношение к вопросу.

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

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

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

У меня есть служба, настроенная на то, чтобы выполнять выборку и установку файлов 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);
        });
    });
  }

Это все отлично работает.

Внутри моего клиентского кода я создал компонент.

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
              }
            }}
          />
        );
      }}
    />
  );
};

ПРОБЛЕМА (тел. Др):

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

Внутри моего компонента PrivateRoute токен авторизации регистрирует 'undefined' в сгенерированном сервером коде и возвращает правильное значение на стороне клиента.

1 Ответ

1 голос
/ 15 апреля 2019

Как universal-cookie lib получает куки? Из документов вам нужно передать заголовок 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

Я бы посоветовал вам провести рефакторинг этого кода, чтобы ваш компонент не знал источник данных (cookie).

Один из распространенных вариантов - поместить его в хранилище при наличии любого хранилища (может быть и в начальном хранилище).

При таком подходе вам нужно будет прочитать cookie на стороне клиента (при инициализации хранилища в этом случае читать cookie из document.cookie) и на стороне сервера (при инициализации хранилища, в этом случае прочитать его из объект запроса).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...