Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: spa ssr渲染模式时layout也需要获取ctx和初始数据 #3

Closed
EvanLiu2968 opened this issue Oct 8, 2018 · 1 comment

Comments

@EvanLiu2968
Copy link

EvanLiu2968 commented Oct 8, 2018

现象:使用spa ssr渲染模式时,页面入口可以获取到服务端的ctx和初始数据,但在layout里面无法获取ctx和初始数据,正常多页面启用loader或者客户端渲染时是可以在layout获取到ctx的,没看出明白问题在哪?

预期:spa ssr渲染模式时layout也需要获取ctx和初始数据

version:egg-view-react-ssr@2.3.1

demo code
spa ssr demo entry

const serverRender = (context, options)=> {
  const { ctx, request, helper, url} = context.state;
  console.log("==================context")
  // console.log(context) // 可以拿到ctx
  const branch = matchRoutes(routes, url);
  const promises = branch.map(({route}) => {
    const fetch = route.component.fetch;
    return fetch instanceof Function ? fetch(ctx) : Promise.resolve(null)
  });
  return Promise.all(promises).then(data => {
    const initState = context.state;
    data.forEach(item => {
      Object.assign(initState, item);
    });
    context.state = Object.assign({}, context.state, initState);
    const store = create(initState);
    return () =>(
      <Layout>
        <Provider store={store}>
          <StaticRouter basename="/ssrdemo" location={url} context={{}}>
            <App url={url}/>
          </StaticRouter>
        </Provider>
      </Layout>
    )
  });
};

layout.js

export default class Layout extends React.Component {
  render() {
    let { ctx, request, helper, ...initState } = this.props;
    console.log('===================layout')
    console.log(this.props) // 无法拿到ctx
    // const serialize = require('serialize-javascript');
    // initState = initState.state || initState;
    return (
      <html>
        <head>
          <title>{this.props.title}</title>
          <meta charSet="utf-8"></meta>
          <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"></meta>
          <meta httpEquiv="X-UA-Compatible" content="IE=edge"></meta>
          <meta name="keywords" content={this.props.keywords}></meta>
          <meta name="description" content={this.props.description}></meta>
          { EASY_ENV_IS_PROD && (
            <script dangerouslySetInnerHTML={{__html: baiduTongji}}></script>
          ) }
          { ctx && ctx.query.debug==='vconsole' && (
            <React.Fragment>
              <script src="https://cdnjs.cloudflare.com/ajax/libs/vConsole/3.2.0/vconsole.min.js"></script>
              <script dangerouslySetInnerHTML={{__html:`new VConsole();`}}></script>
            </React.Fragment>
          ) }
          <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.5.7/core.min.js"></script>
          <script dangerouslySetInnerHTML={{__html:`document.write('${ie9Mixins}')`}}></script>
          { ctx && !/\/lowVersionBrowser/.test(ctx.request.url) && <script dangerouslySetInnerHTML={{__html:`document.write('${ie8Mixins}')`}}></script> }
          <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"></link>
        </head>
        <body>
          <div id="app">{this.props.children}</div>
          {/* <script id="__INITIAL_STATE__" dangerouslySetInnerHTML={{__html: `window.__INITIAL_STATE__= ${serialize(initState, { isJSON: true })};`}}></script> */}
        </body>
      </html>
    )
  }
}
@EvanLiu2968
Copy link
Author

sorry,忘记spa的ssr是手动引入的了,直接在layout传值就可以了<Layout {...context.state}>

完整代码应该是这样的

const serverRender = (context, options)=> {
  const { ctx, request, helper, url} = context.state;
  console.log("==================context")
  // console.log(context)
  const branch = matchRoutes(routes, url);
  const promises = branch.map(({route}) => {
    const fetch = route.component.fetch;
    return fetch instanceof Function ? fetch(ctx) : Promise.resolve(null)
  });
  return Promise.all(promises).then(data => {
    const initState = context.state;
    data.forEach(item => {
      Object.assign(initState, item);
    });
    context.state = Object.assign({}, context.state, initState);
    const store = create(initState);
    return () =>(
      <Layout {...context.state}>
        <Provider store={store}>
          <StaticRouter basename="/ssrdemo" location={url} context={{}}>
            <App url={url}/>
          </StaticRouter>
        </Provider>
      </Layout>
    )
  });
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant