最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Is there a cleaner way of getting current URL in both client and server side in isomorphic react apps? - Stack Over

programmeradmin0浏览0评论

I am developing an app based in this React Redux boilerplate. In one ponent I need to get the current URL when ponent is mounted in order to generate a shareable URL for social media. Than ponent is being accesible from dynamically generated URLs with React Router. In client side I wouldn't have any problem by getting it through javascript document object but the problem lies server side.

I thought about making available in the Redux store the Node.js environment data kept in this config.js file, where hostname is kept

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

and with the location object of React Router set as props in the ponent get the pathname and fully construct the URL.

What I have done is to create a simple reducer with an initial state to keep the Node.js config enviroment data and just the default action to include in my bineReducers function with the other app reducers.

const initialState = { 
  config: {}
};

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

And then I injected the Node.js object with the environment data in the creation of the store, as initial state data, in my server.js file.

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

Thus I have available the hostname and I am able in the ponent to construct its full url both client and server side through Redux store.

But, is there any simpler / cleanest way? I am afraid I might be overkilling it or creating any security issue to my app.

I am developing an app based in this React Redux boilerplate. In one ponent I need to get the current URL when ponent is mounted in order to generate a shareable URL for social media. Than ponent is being accesible from dynamically generated URLs with React Router. In client side I wouldn't have any problem by getting it through javascript document object but the problem lies server side.

I thought about making available in the Redux store the Node.js environment data kept in this config.js file, where hostname is kept

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

and with the location object of React Router set as props in the ponent get the pathname and fully construct the URL.

What I have done is to create a simple reducer with an initial state to keep the Node.js config enviroment data and just the default action to include in my bineReducers function with the other app reducers.

const initialState = { 
  config: {}
};

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

And then I injected the Node.js object with the environment data in the creation of the store, as initial state data, in my server.js file.

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

Thus I have available the hostname and I am able in the ponent to construct its full url both client and server side through Redux store.

But, is there any simpler / cleanest way? I am afraid I might be overkilling it or creating any security issue to my app.

Share Improve this question edited Feb 13, 2018 at 15:20 Dez asked Mar 9, 2017 at 13:16 DezDez 5,8488 gold badges46 silver badges52 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 2

I was having this issue when attempting to use Helmet server-side. I passed in the request as a prop to my main <App> ponent and then use either that request object (server-side) or the window object (client-side).

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()

Is this "proper" or "best practice"? No idea, but it works well and is easy to follow :)

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论