Provides an universal HOC (higher-order component) for React components and populates the component props and the getInitialProps args object with an env property, which gives access to cookies, language(s), userAgent and doNotTrack in a standardized way. If you are using Next.js / After.js you will get also access to the IP address and benefit heavily from the standardized API on server-side and client-side.
- Save time: Most important thing: short if-else-blocks, no formatting needed, no old-browser-carrying, etc.
- Standardized:
Accept-Language
&&User-Agent
&&Cookie
&&DNT
headers are parsed and available in the same format as inwindow
. (same parsing libraries / functions && reformatting && backwards compatibility) - Access to IP address: IP address is available client-side and there are checked 10+ properties to ensure you always get the best match. Supports enabling/disabling of proxy trusting.
- Fully tested: Tested for strange edge cases, missing HTTP headers or missing window properties.
- Some nice to have features:
- Console.warns() while process.ENV.NODE_ENV === 'development', if server props !== client props
- Possibility to only use props from the HTTP request
Feature requests for additional properties are welcomed
You can install it directly from npm:
npm i env-hoc
or, if you are using yarn:
yarn add env-hoc
with decorators
Just import the package and add it as a decorator to every page where you want to have access to the env
object.
import React from 'react';
import withEnv from 'env-hoc';
@withEnv
class Environment extends React.Component {
//getInitialProps is a Next.js/After.js thing, just ignore it, if you aren't using one of them
static getInitialProps(args) {
console.log('args.env:', args.env);
}
render() {
console.log('this.props:', this.props.env);
return (
<div>
<h1>Environment</h1>
<pre>userAgent: {this.props.env.userAgent}</pre>
<pre>language: {this.props.env.language}</pre>
<pre>languages: {this.props.env.languages.join(', ')}</pre>
<pre>ipAddress: {this.props.env.ipAddress}</pre>
<pre>cookies: {JSON.stringify(this.props.env.cookies)}</pre>
<pre>doNotTrack: {this.props.env.doNotTrack ? 'true' : 'false'}</pre>
</div>
);
}
}
export default Environment;
/* CONSOLE OUTPUT:
args.env: { userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
language: 'de-DE',
languages: [ 'de-DE', 'de', 'en-US', 'en', 'bs', 'hr' ],
cookies: {},
doNotTrack: true,
ipAddress: '::1' }
this.props: { userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
language: 'de-DE',
languages: [ 'de-DE', 'de', 'en-US', 'en', 'bs', 'hr' ],
cookies: {},
doNotTrack: true,
ipAddress: '::1' }
*/
Just import the package and wrap it around every page where you want to have access to the env
object.
import React from 'react';
import withEnv from 'env-hoc';
class Environment extends React.Component {
//getInitialProps is a Next.js/After.js thing, just ignore it, if you aren't using one of them
static getInitialProps(args) {
console.log('args.env:', args.env);
}
render() {
console.log('this.props:', this.props.env);
return (
<div>
<h1>Environment</h1>
<pre>userAgent: {this.props.env.userAgent}</pre>
<pre>language: {this.props.env.language}</pre>
<pre>languages: {this.props.env.languages.join(', ')}</pre>
<pre>ipAddress: {this.props.env.ipAddress}</pre>
<pre>cookies: {JSON.stringify(this.props.env.cookies)}</pre>
<pre>doNotTrack: {this.props.env.doNotTrack ? 'true' : 'false'}</pre>
</div>
);
}
}
export default withEnv(Environment);
//without decorator
withEnv({
trustProxy: false,
})(Environment);
//with decorator
@withEnv({
trustProxy: false,
})
class Environment extends React.Component {}
You can also configure withEnv once in a file and then import it from there when needed.
//file: configuredWithEnv.js
export default withEnv({
trustProxy: false,
});
//file: page.js
import configuredWithEnv from './configuredWithEnv';
//with decorator
@configuredWithEnv
export default class Environment extends React.Component {}
//without decorator
configuredWithEnv(class Environment extends React.Component {})
- trustProxy: (boolean) If true, then it trusts proxy HTTP headers.
- cookieParser: (object) Is beeing passed to the parse function of the cookie package.
- debug: (boolean) If true, then it console.warns() you about different client / server behaviour.
- useServerProps: (boolean/object) If true, only the props from server-rendering are used. You can also pass an object with keys matching the key from this.props.env and enable usage of server props only partially. For example:
withEnv({
useServerProps: {
cookies: true,
languages: true,
},
});
withEnv({
trustProxy: true,
cookieParser: {},
debug: process.env.NODE_ENV === 'development',
useServerProps: false,
});
If you want to be a good programmer or support very old browsers, you should still check if a property is available, if some data isn't available, then it will be always for:
- all properties except cookies:
null
- cookies:
{}
So a short if () {}
will do it mostly.