refactor: state++
This commit is contained in:
parent
eb46f3a591
commit
785ab39bbd
|
@ -1,27 +1,14 @@
|
||||||
import merge from 'deepmerge';
|
import merge from 'deepmerge';
|
||||||
import {combineReducers} from 'redux';
|
import {routerMiddleware} from 'connected-react-router';
|
||||||
import {connectRouter, routerMiddleware} from 'connected-react-router';
|
|
||||||
|
import {stateReducer, subscription} from '~/common/state';
|
||||||
|
|
||||||
import app from '~/common/state/app';
|
|
||||||
import chat from '~/common/state/chat';
|
|
||||||
import createHistory from '~/common/state/history';
|
|
||||||
import {storageSubscription} from '~/common/state/storage';
|
|
||||||
import user from '~/common/state/user';
|
|
||||||
import usernames from '~/common/state/usernames';
|
|
||||||
import createCommonStore from '~/common/store';
|
import createCommonStore from '~/common/store';
|
||||||
|
|
||||||
import {middleware as effectsMiddleware} from './effects';
|
import {middleware as effectsMiddleware} from './effects';
|
||||||
|
|
||||||
export default function createStore(options = {}) {
|
export default function createStore(options = {}) {
|
||||||
const {history} = options;
|
const {history} = options;
|
||||||
const reducer = combineReducers({
|
|
||||||
app,
|
|
||||||
chat,
|
|
||||||
history: createHistory(history),
|
|
||||||
router: connectRouter(history),
|
|
||||||
user,
|
|
||||||
usernames,
|
|
||||||
});
|
|
||||||
const store = createCommonStore(
|
const store = createCommonStore(
|
||||||
merge(
|
merge(
|
||||||
options,
|
options,
|
||||||
|
@ -30,10 +17,10 @@ export default function createStore(options = {}) {
|
||||||
routerMiddleware(history),
|
routerMiddleware(history),
|
||||||
effectsMiddleware,
|
effectsMiddleware,
|
||||||
],
|
],
|
||||||
reducer,
|
reducer: stateReducer(history),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
store.subscribe(storageSubscription(store));
|
store.subscribe(subscription(store));
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,13 @@ export const rightIsOpenSelector = createSelector(
|
||||||
);
|
);
|
||||||
|
|
||||||
const slice = createSlice({
|
const slice = createSlice({
|
||||||
name: 'app',
|
name: 'reddichat/app',
|
||||||
initialState: storage(appSelector) || {
|
initialState: {
|
||||||
leftActiveIndex: 0,
|
leftActiveIndex: 0,
|
||||||
leftIsOpen: true,
|
leftIsOpen: true,
|
||||||
rightActiveIndex: 0,
|
rightActiveIndex: 0,
|
||||||
rightIsOpen: true,
|
rightIsOpen: true,
|
||||||
|
...(storage(appSelector) || {}),
|
||||||
},
|
},
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
extraReducers: {},
|
extraReducers: {},
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
/* eslint-disable no-param-reassign */
|
|
||||||
import {
|
import {
|
||||||
createSelector,
|
createSelector,
|
||||||
createSlice,
|
createSlice,
|
||||||
} from '@reduxjs/toolkit';
|
} from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import hydration from './hydration';
|
import hydration from './hydration';
|
||||||
import storage from './storage';
|
import storage, {localStorage} from './storage';
|
||||||
|
|
||||||
export const chatSelector = (state) => state.chat;
|
export const chatSelector = (state) => state.chat;
|
||||||
|
|
||||||
|
@ -45,7 +44,7 @@ export const channelMessagesSelector = createSelector(
|
||||||
);
|
);
|
||||||
|
|
||||||
const slice = createSlice({
|
const slice = createSlice({
|
||||||
name: 'chat',
|
name: 'reddichat/chat',
|
||||||
initialState: {
|
initialState: {
|
||||||
channels: {},
|
channels: {},
|
||||||
input: {},
|
input: {},
|
||||||
|
@ -53,6 +52,10 @@ const slice = createSlice({
|
||||||
...(hydration('chat') || {}),
|
...(hydration('chat') || {}),
|
||||||
...(storage(chatSelector) || {}),
|
...(storage(chatSelector) || {}),
|
||||||
},
|
},
|
||||||
|
/* eslint-disable no-param-reassign */
|
||||||
|
extraReducers: {
|
||||||
|
[localStorage]: ({input}) => ({input}),
|
||||||
|
},
|
||||||
reducers: {
|
reducers: {
|
||||||
addMessage: ({
|
addMessage: ({
|
||||||
channels,
|
channels,
|
||||||
|
@ -117,6 +120,7 @@ const slice = createSlice({
|
||||||
submitLeave: () => {},
|
submitLeave: () => {},
|
||||||
submitMessage: () => {},
|
submitMessage: () => {},
|
||||||
},
|
},
|
||||||
|
/* eslint-enable no-param-reassign */
|
||||||
});
|
});
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
|
|
27
src/common/state/index.js
Normal file
27
src/common/state/index.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import {connectRouter} from 'connected-react-router';
|
||||||
|
import {combineReducers} from 'redux';
|
||||||
|
|
||||||
|
import app from './app';
|
||||||
|
import chat from './chat';
|
||||||
|
import createHistory from './history';
|
||||||
|
import {storageSubscription} from './storage';
|
||||||
|
import user from './user';
|
||||||
|
import usernames from './usernames';
|
||||||
|
|
||||||
|
export const stateReducer = (history) => combineReducers({
|
||||||
|
app,
|
||||||
|
chat,
|
||||||
|
history: createHistory(history),
|
||||||
|
router: connectRouter(history),
|
||||||
|
user,
|
||||||
|
usernames,
|
||||||
|
});
|
||||||
|
|
||||||
|
const subscriptionReducer = combineReducers({
|
||||||
|
app,
|
||||||
|
chat,
|
||||||
|
user,
|
||||||
|
usernames,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const subscription = (store) => storageSubscription(store, subscriptionReducer);
|
|
@ -1,11 +1,22 @@
|
||||||
import throttle from 'lodash.throttle';
|
import throttle from 'lodash.throttle';
|
||||||
|
import {createAction} from '@reduxjs/toolkit';
|
||||||
|
|
||||||
export const storageSubscription = (store) => (
|
export const localStorage = createAction('reddichat/localStorage');
|
||||||
throttle(() => localStorage.setItem('redux-state', JSON.stringify(store.getState())), 1000)
|
|
||||||
|
export const storageSubscription = (store, reducer) => (
|
||||||
|
throttle(
|
||||||
|
() => (
|
||||||
|
window.localStorage.setItem(
|
||||||
|
'redux-state',
|
||||||
|
JSON.stringify(reducer(store.getState(), localStorage())),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
1000,
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
export default (selector) => {
|
export default (selector) => {
|
||||||
const state = localStorage.getItem('redux-state');
|
const state = window.localStorage.getItem('redux-state');
|
||||||
if (!state) {
|
if (!state) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import {LOCATION_CHANGE} from 'connected-react-router';
|
import {LOCATION_CHANGE} from 'connected-react-router';
|
||||||
|
import merge from 'deepmerge';
|
||||||
import {
|
import {
|
||||||
createSelector,
|
createSelector,
|
||||||
createSlice,
|
createSlice,
|
||||||
|
@ -7,6 +8,7 @@ import {
|
||||||
import {addMessage, join, leave} from './chat';
|
import {addMessage, join, leave} from './chat';
|
||||||
|
|
||||||
import hydration from './hydration';
|
import hydration from './hydration';
|
||||||
|
import storage, {localStorage} from './storage';
|
||||||
|
|
||||||
export const userSelector = (state) => state.user;
|
export const userSelector = (state) => state.user;
|
||||||
|
|
||||||
|
@ -104,8 +106,9 @@ export const unreadForChannelSelector = createSelector(
|
||||||
);
|
);
|
||||||
|
|
||||||
const slice = createSlice({
|
const slice = createSlice({
|
||||||
name: 'user',
|
name: 'reddichat/user',
|
||||||
initialState: {
|
initialState: merge.all([
|
||||||
|
{
|
||||||
blocked: [],
|
blocked: [],
|
||||||
favorites: [],
|
favorites: [],
|
||||||
focus: '',
|
focus: '',
|
||||||
|
@ -115,9 +118,34 @@ const slice = createSlice({
|
||||||
recent: [],
|
recent: [],
|
||||||
redditUsername: 'anonymous',
|
redditUsername: 'anonymous',
|
||||||
unread: {},
|
unread: {},
|
||||||
...(hydration('user') || {isAnonymous: true}),
|
|
||||||
},
|
},
|
||||||
|
hydration('user') || {isAnonymous: true},
|
||||||
|
storage(userSelector) || {},
|
||||||
|
], {arrayMerge: (target, source) => Array.from(new Set(source.concat(target)).values())}),
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
|
extraReducers: {
|
||||||
|
[addMessage]: ({focus, unread}, {payload: {channel}}) => {
|
||||||
|
if (focus !== channel) {
|
||||||
|
unread[channel] = (unread[channel] || 0) + 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[join]: ({recent}, {payload: {channel}}) => {
|
||||||
|
if (-1 === recent.indexOf(channel)) {
|
||||||
|
recent.push(channel.substr(3));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[leave]: ({unread}, {payload: {channel}}) => {
|
||||||
|
delete unread[channel];
|
||||||
|
},
|
||||||
|
[localStorage]: ({recent}) => ({recent}),
|
||||||
|
[LOCATION_CHANGE]: (state, {payload: {location: {pathname}}}) => {
|
||||||
|
const {unread} = state;
|
||||||
|
state.focus = pathname.match(/^\/chat\//) ? pathname.substr('/chat'.length) : '';
|
||||||
|
if (unread[state.focus]) {
|
||||||
|
delete unread[state.focus];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
reducers: {
|
reducers: {
|
||||||
addFriendship: ({friendship}, {payload}) => {
|
addFriendship: ({friendship}, {payload}) => {
|
||||||
const index = friendshipIndex(friendship, payload);
|
const index = friendshipIndex(friendship, payload);
|
||||||
|
@ -156,28 +184,6 @@ const slice = createSlice({
|
||||||
blocked.splice(blocked.indexOf(payload), 1);
|
blocked.splice(blocked.indexOf(payload), 1);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
extraReducers: {
|
|
||||||
[addMessage]: ({focus, unread}, {payload: {channel}}) => {
|
|
||||||
if (focus !== channel) {
|
|
||||||
unread[channel] = (unread[channel] || 0) + 1;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[join]: ({recent}, {payload: {channel}}) => {
|
|
||||||
if (-1 === recent.indexOf(channel) && channel.charCodeAt(1) === 'r'.charCodeAt(0)) {
|
|
||||||
recent.push(channel.substr(3));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[leave]: ({unread}, {payload: {channel}}) => {
|
|
||||||
delete unread[channel];
|
|
||||||
},
|
|
||||||
[LOCATION_CHANGE]: (state, {payload: {location: {pathname}}}) => {
|
|
||||||
const {unread} = state;
|
|
||||||
state.focus = pathname.match(/^\/chat\//) ? pathname.substr('/chat'.length) : '';
|
|
||||||
if (unread[state.focus]) {
|
|
||||||
delete unread[state.focus];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
/* eslint-enable no-param-reassign */
|
/* eslint-enable no-param-reassign */
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
} from '~/common/state/chat';
|
} from '~/common/state/chat';
|
||||||
|
|
||||||
import hydration from './hydration';
|
import hydration from './hydration';
|
||||||
|
import storage from './storage';
|
||||||
|
|
||||||
export const usernamesSelector = (state) => state.usernames;
|
export const usernamesSelector = (state) => state.usernames;
|
||||||
|
|
||||||
|
@ -17,10 +18,13 @@ export const usernameSelector = createSelector(
|
||||||
(usernames, id) => usernames[id],
|
(usernames, id) => usernames[id],
|
||||||
);
|
);
|
||||||
|
|
||||||
/* eslint-disable no-param-reassign */
|
|
||||||
const slice = createSlice({
|
const slice = createSlice({
|
||||||
name: 'usernames',
|
name: 'reddichat/usernames',
|
||||||
initialState: hydration('usernames') || {},
|
initialState: {
|
||||||
|
...(hydration('usernames') || {}),
|
||||||
|
...(storage(usernamesSelector) || {}),
|
||||||
|
},
|
||||||
|
/* eslint-disable no-param-reassign */
|
||||||
extraReducers: {
|
extraReducers: {
|
||||||
[join]: (state, {payload: {usernames}}) => ({...state, ...usernames}),
|
[join]: (state, {payload: {usernames}}) => ({...state, ...usernames}),
|
||||||
[joined]: (state, {payload: {id, name}}) => ({...state, [id]: name}),
|
[joined]: (state, {payload: {id, name}}) => ({...state, [id]: name}),
|
||||||
|
@ -28,8 +32,8 @@ const slice = createSlice({
|
||||||
reducers: {
|
reducers: {
|
||||||
setUsernames: (state, {payload}) => ({...state, ...payload}),
|
setUsernames: (state, {payload}) => ({...state, ...payload}),
|
||||||
},
|
},
|
||||||
|
/* eslint-enable no-param-reassign */
|
||||||
});
|
});
|
||||||
/* eslint-enable no-param-reassign */
|
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
setUsernames,
|
setUsernames,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user