javascript - 在同构 react 应用程序中,是否有一种更简洁的方法可以在客户端和服务器端获取当前 URL?

标签 javascript node.js reactjs react-router react-redux

我正在开发一个基于 this 的应用程序React Redux 样板。 在一个组件中,我需要在安装组件时获取当前 URL,以便为社交媒体生成可共享的 URL。使用 React Router 从动态生成的 URL 可以访问组件。在客户端,通过 javascript document 对象获取它不会有任何问题,但问题在于服务器端。

我考虑在 Redux 存储中提供保存在这个 config.js 文件中的 Node.js 环境数据,其中保存了主机名

// Node.js environment file config.js    
require('babel-polyfill');

const environment = { 
  development: {
    isProduction: false
  },  
  production: {
    isProduction: true
  }
}[process.env.NODE_ENV || 'development'];

module.exports = Object.assign({
  host: process.env.HOST || 'localhost',
  port: process.env.PORT,
  apiHost: process.env.APIHOST || 'localhost',
  apiPort: process.env.APIPORT
}, environment);

并且将 React Router 的 location 对象设置为组件中的 props,获取路径名并完全构建 URL。

我所做的是创建一个简单的 reducer ,它具有初始状态以保留 Node.js 配置环境数据,并且只是包含在我的 combineReducers 函数中与其他应用 reducer 的默认操作。

const initialState = { 
  config: {}
};

export default function config(state = initialState, action = {}) {
  switch (action.type) {
    default:
      return state;
  }
}

然后我在我的 server.js 文件中注入(inject)了 Node.js 对象和创建商店时的环境数据,作为初始状态数据。

import config from './config';
...
const store = createStore(memoryHistory, client, {config});
...

因此我有可用的主机名,并且我可以在组件中通过 Redux 存储在客户端和服务器端构造其完整的 url。

但是,有没有更简单/最干净的方法?我担心我可能会过度使用它或给我的应用程序带来任何安全问题。

最佳答案

我在尝试使用 Helmet 服务器端时遇到了这个问题。我将请求作为 Prop 传递给我的主要 <App>组件,然后使用该请求对象(服务器端)或窗口对象(客户端)。

App.js

render() {

    // Get full url from client or server
    let fullURL = ''
    if(typeof window !== 'undefined'){
        fullURL = window.location.protocol + '//' + window.location.host + this.props.location.pathname
    }else if(this.props.serverRequest){
        fullURL = this.props.serverRequest.headers.host + '/' + this.props.location.pathname
    }

    const urlTag = fullURL === '' ? null : <meta property="og:url" content={fullURL} />
    const linkTag = fullURL === '' ? null : <link rel="canonical" href={fullURL} />

    const helmet = this.props.siteInfo.site
        ? <Helmet>
            <title>{this.props.siteInfo.site.title}</title>
            <meta property="twitter:title" content={this.props.siteInfo.site.title} />
            {urlTag}
            {linkTag}
            <meta property="og:type" content="website" />
          </Helmet>
        : null

    return (
        <div>
            {helmet}
            <Notices />
            <div className="body">
                <Header />
                <Body />
            </div>
            <Footer />
        </div>
    )
}

server.js

const markup = renderToString(
    <Provider store={store}>
        <StaticRouter location={req.url} context={context}>
            <App serverRequest={req} />
        </StaticRouter>
    </Provider>
)

const helmet = Helmet.renderStatic()

这是“正确的”还是“最佳实践”?不知道,但它运作良好且易于理解:)

关于javascript - 在同构 react 应用程序中,是否有一种更简洁的方法可以在客户端和服务器端获取当前 URL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42696426/

相关文章:

javascript - 为什么我收到 "Refusing to install purify-css as a dependency of itself"错误?

reactjs - 如果在 useEffect 之后没有发生任何事情,则进行 react 测试

reactjs - 使用异步数据初始化组件

javascript - Node.js 子进程中的数据丢失

javascript - react 语义用户界面 : How to set focus for input field of dropdown element

javascript - 数据表sInfo在表为空时更改文本

javascript - 使用 CSS 按恒定量翻译元素以获得更流畅的动画?

javascript - else if 语句不起作用

jquery - 声明 javascript 函数、jQuery

node.js - 如何处理 Node.js 中的不同错误类型