Skip to content

Commit

Permalink
added immutable support
Browse files Browse the repository at this point in the history
  • Loading branch information
yeojz committed Feb 28, 2017
1 parent ca92722 commit d0815ed
Show file tree
Hide file tree
Showing 12 changed files with 117 additions and 45 deletions.
11 changes: 8 additions & 3 deletions src/createIntlObject.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import getValue from './utils/getValue';
import formatMessage from './formatMessage';

export default (intl) => ({
function createIntlObject(intl) {
return {
formatMessage: formatMessage(intl),
locale: intl.locale
});
locale: getValue(intl, 'locale')
}
}

export default createIntlObject;
7 changes: 4 additions & 3 deletions src/createMapStateToProps.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import getValue from './utils/getValue';
import createIntlObject from './createIntlObject';
import intlSelector from './intlSelector';

export function createMapStateToProps(selector = intlSelector) {
function createMapStateToProps(selector = intlSelector) {
return (state) => {
const intl = selector(state);

return {
intl: createIntlObject(intl),
key: intl.locale
};
key: getValue(intl, 'locale')
}
};
}

Expand Down
26 changes: 4 additions & 22 deletions src/formatMessage.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,22 @@
import invariant from 'invariant';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import isFunction from 'lodash/isFunction';

import getMessage from './utils/getMessage';
import getValue from './utils/getValue';
import {LOG_PREFIX} from './constants';

const ENV = process.env.NODE_ENV;

function isImmutable(state) {
return isFunction(state.get)
&& isFunction(state.getIn);
}

function getLocale(state) {
if (isImmutable(state)) {
return state.get('locale');
}
return state.locale;
}

function parseMessage(message, values = {}) {
const parseMessage = (message, values = {}) => {
if (message && isFunction(message)) {
return message(values);
}
return void 0;
}

function getMessage(state, id) {
if (isImmutable(state)) {
return state.getIn(['messages', id], '');
}
return get(state, ['messages', id], '');
}

function formatMessage(state = {}) {
const locale = getLocale(state);
const locale = getValue(state, 'locale');

if (!locale) {
return () => '';
Expand Down
2 changes: 1 addition & 1 deletion src/injectIntl.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import invariant from 'invariant';
import {LOG_PREFIX} from './constants';
import createMapStateToProps from './createMapStateToProps';

export function injectIntl(
function injectIntl(
connect,
mapStateToProps = createMapStateToProps()
) {
Expand Down
38 changes: 25 additions & 13 deletions src/intlReducer.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
import isImmutable from './utils/isImmutable';
import {UPDATE_ACTION} from './constants';

export const initialState = () => ({
cacheDisable: false,
ecmaSupport: false,
locale: '',
messages: {}
});
function initialState() {
return {
cacheDisable: false,
ecmaSupport: false,
locale: '',
messages: {}
}
}

function setImmutable(state, payload) {
return state.merge(payload);
}

export function intlReducer(state = initialState(), action = {}) {
function intlReducer(state = initialState(), action = {}) {

if (action && action.type === UPDATE_ACTION) {
return {
...state,
...action.payload
};
if (!action || action.type !== UPDATE_ACTION) {
return state;
}

return state;
if (isImmutable(state)) {
return setImmutable(state, action.payload);
}

return {
...state,
...action.payload
}
}

export {initialState as initialState};
export default intlReducer;
9 changes: 8 additions & 1 deletion src/intlSelector.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import MessageFormat from 'messageformat';
import isEmpty from 'lodash/isEmpty';
import isImmutable from './utils/isImmutable';

const isIntlValid = (intl) => (
!isEmpty(intl) && intl.locale
Expand All @@ -16,11 +17,17 @@ const compileMessages = (intl) => (
.compile(intl.messages)
);

const getIntl = (state) => (
isImmutable(state.intl)
? state.intl.toJS()
: state.intl
);

export function createIntlSelector() {
let cache = {};

return (state = {}) => {
const {intl} = state;
const intl = getIntl(state);

if (!isIntlValid(intl)) {
cache = {}
Expand Down
4 changes: 2 additions & 2 deletions src/updateIntl.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import {initialState} from './intlReducer';

const ACCEPTABLE_KEYS = Object.keys(initialState());

export function updateIntl(keys = {}) {
function updateIntl(keys = {}) {
return {
type: UPDATE_ACTION,
payload: pick(keys, ACCEPTABLE_KEYS)
};
}
}

export default updateIntl;
11 changes: 11 additions & 0 deletions src/utils/getMessage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import get from 'lodash/get';
import isImmutable from './isImmutable';

function getMessage(state, id) {
if (isImmutable(state)) {
return state.getIn(['messages', id], '');
}
return get(state, ['messages', id], '');
}

export default getMessage;
11 changes: 11 additions & 0 deletions src/utils/getValue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import get from 'lodash/get';
import isImmutable from './isImmutable';

function getValue(state, value) {
if (isImmutable(state)) {
return state.get(value);
}
return get(state, value);
}

export default getValue;
7 changes: 7 additions & 0 deletions src/utils/isImmutable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import isFunction from 'lodash/isFunction';

function isImmutable(state = {}) {
return isFunction(state.toJS);
}

export default isImmutable;
11 changes: 11 additions & 0 deletions tests/intlReducer.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {expect} from 'chai';
import {fromJS} from 'immutable';
import {UPDATE_ACTION} from '../src/constants';
import intlReducer, {initialState} from '../src/intlReducer';

Expand Down Expand Up @@ -27,6 +28,16 @@ describe('intlReducer', function () {
expect(result).to.deep.eql(expected);
});

it('updates state even if immutable', function () {
const action = {
type: UPDATE_ACTION,
payload: getUpdatePayload()
}
const expected = fromJS(getUpdatePayload());
const result = intlReducer(fromJS(initialState()), action);
expect(result.toJS()).to.deep.equal(expected.toJS());
});

function getUpdatePayload() {
return {
cacheDisable: false,
Expand Down
25 changes: 25 additions & 0 deletions tests/intlSelector.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {expect} from 'chai';
import {fromJS} from 'immutable';
import mockMessageFormat from './mocks/messageformat';
import defaultIntlSelector, {createIntlSelector} from '../src/intlSelector';

Expand Down Expand Up @@ -36,6 +37,30 @@ describe('intlSelector', function () {
expect(round2.messages.alternate).to.be.undefined;
});

it('returns empty object when unable to locale intl even when state is immutable', function () {
const intlSelector = createIntlSelector();
const result = intlSelector({
intl: fromJS({})
});
expect(result).to.be.empty;
});

it('returns cache when cache intl and reducer intl is the same even when state is immutable.', function () {
const intlSelector = createIntlSelector();

let state1 = getState();
state1.intl = fromJS(state1.intl);
const round1 = intlSelector(state1);
expect(round1.messages.test).to.not.be.undefined;
expect(round1.messages.alternate).to.be.undefined;

let state2 = getAlternateState();
state2.intl = fromJS(state2.intl);
const round2 = intlSelector(state2);
expect(round2.messages.test).to.not.be.undefined;
expect(round2.messages.alternate).to.be.undefined;
});

function getState() {
return {
intl: {
Expand Down

0 comments on commit d0815ed

Please sign in to comment.