Reactn(Redux)服务器端渲染问题

时间:2019-09-10 14:14:04

标签: javascript reactjs redux

我正在使用reactn来管理我的全局状态,而不是直接使用redux。我有一个SSR react应用,但是在使全局状态正常工作时遇到了一些问题。据我了解,我应该使用它们的Provider组件(https://github.com/CharlesStover/reactn/blob/master/Provider.md)。总体而言,我正在服务器和客户端上创建一个新的Provider,然后在我的每个React组件中使用相同的Provider组件。

我有两个主要问题:

  1. 我是否正确设置了提供程序?
  2. 为什么我调用setGlobal()时组件没有更新。在我的组件之一中,我有
export default StateManager.Provider.withGlobal(
  ({ loggedIn, currentUser, signInError }: Partial<State>) => ({
    currentUser,
    signInError
  })
)(UserSignInPage);

然后,当用户登录时,我会拨打以下电话:

StateManager.Provider.setGlobal({
            loggedIn: true,
            currentUser: res.user,
          });

以下是我的提供商,服务器和客户端代码的精简版:

// StateManager.ts
export default class StateManger {
  static reducers: Reducers = {
    addCardToBeComposed
  };
  static defaultState: State = {
    device: DeviceType.MOBILE,
    currentUser: null,
    loggedIn: false
  };

  static Provider: any = createProvider(
    StateManger.defaultState,
    StateManger.reducers
  );

  static getState(): State {
    try {
      const serializedState: string = Cookies.get('appState');
      return JSON.parse(serializedState) || StateManger.defaultState;
    } catch (err) {
      console.warn('Error trying to getState', err);
    }
  }

  static saveState(state: State): void {
    try {
      const serializedState: string = JSON.stringify(state);
      Cookies.set('appState', serializedState);
    } catch (err) {
      console.warn('Error saving state data', err, state);
    }
  }

  static createProvider(state: State): ReactNProvider {
    StateManger.Provider = createProvider(state, StateManger.reducers);
    return StateManger.Provider;
  }
}

Server.ts

    const styledComponentsSheet = new ServerStyleSheet();
    const materialSheets = new ServerStyleSheets();
    const context: any = {};
    const cookieAppState = req.cookies.appState;
    const appStateObj = JSON.parse(cookieAppState);
    const appState: any = {
      ...StateManager.defaultState,
      appStateObj
    };
    StateManager.createProvider(appState);

    const markup: string = renderToString(
      styledComponentsSheet.collectStyles(
        materialSheets.collect(
          <StaticRouter context={context} location={req.url}>
            <StateManager.Provider>
              <App />
            </StateManager.Provider>
          </StaticRouter>
        )
      )
    );
    const materialSheet = renderToString(materialSheets.getStyleElement());
    const sheet = styledComponentsSheet.getStyleElement();

    const styleSheet: string = renderToString(<>{sheet}</>);
    res.send(`<html lang="en" dir="ltr">
                  <head>
                    <meta charSet="utf-8" />
                    <meta
                      name="viewport"
                      content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"
                    />
                    <meta
                      name="theme-color"
                      content={theme.palette.primary.main}
                    />

                    <script>__APP_DATA__ = ${JSON.stringify(appState)}</script>
                    ${materialSheet}
                    ${styleSheet}
                    ${
                      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>
            `);
...

Client.tsx

let Provider = StateManager.createProvider(StateManager.getState());
try {
  Provider = StateManager.createProvider(window.__APP_DATA__);
} catch (e) {
  console.warn('Error tryingt to parse app data from server', e);
}

hydrate(
  <BrowserRouter>
    <Provider>
      <App />
    </Provider>
  </BrowserRouter>,
  document.getElementById('root')
);

0 个答案:

没有答案