aboutsummaryrefslogtreecommitdiff
path: root/src/store
diff options
context:
space:
mode:
authorAshm Walia <40498934+ashmgarv@users.noreply.github.com>2020-12-04 08:50:24 -0800
committerGitHub <noreply@github.com>2020-12-04 11:50:24 -0500
commit0fd892ad288f2e1eaaa4fdf5e1fd6f15dbd45860 (patch)
treed7d53d94c6c4026ac9b325508ebce4706d412ac4 /src/store
parentf620102190629e0b6f180d3ce056d850b1db5aaa (diff)
[TMA - 398 AND TMA-430] Replace Providers with Redux Store (#125)
* First * WIP * Thunk * Some more comments * sc * recent searches and follounfollow * Edit profile dummy * Block / unblock and some cleanup * Replace auth provider * Sc * Delete AP after rebase * Discover users * Cleanup * More cleanup * Replace profile provider * Fixed build failure * Fixed a bug reported * Prevent app crash when backend server is down
Diffstat (limited to 'src/store')
-rw-r--r--src/store/actions/index.ts7
-rw-r--r--src/store/actions/socials.ts38
-rw-r--r--src/store/actions/taggUsers.ts24
-rw-r--r--src/store/actions/user.ts52
-rw-r--r--src/store/actions/userBlock.ts48
-rw-r--r--src/store/actions/userFollow.ts57
-rw-r--r--src/store/actions/userMoments.ts22
-rw-r--r--src/store/actions/userX.ts131
-rw-r--r--src/store/configureStore.ts20
-rw-r--r--src/store/initialStates.ts95
-rw-r--r--src/store/reducers/index.ts7
-rw-r--r--src/store/reducers/taggUsersReducer.ts16
-rw-r--r--src/store/reducers/userBlockReducer.ts25
-rw-r--r--src/store/reducers/userFollowReducer.ts27
-rw-r--r--src/store/reducers/userMomentsReducer.ts15
-rw-r--r--src/store/reducers/userReducer.ts36
-rw-r--r--src/store/reducers/userSocialsReducer.ts21
-rw-r--r--src/store/reducers/userXReducer.ts77
-rw-r--r--src/store/rootReducer.ts30
19 files changed, 748 insertions, 0 deletions
diff --git a/src/store/actions/index.ts b/src/store/actions/index.ts
new file mode 100644
index 00000000..04fa9767
--- /dev/null
+++ b/src/store/actions/index.ts
@@ -0,0 +1,7 @@
+export * from './user';
+export * from './userFollow';
+export * from './userMoments';
+export * from './socials';
+export * from './taggUsers';
+export * from './userBlock';
+export * from './userX';
diff --git a/src/store/actions/socials.ts b/src/store/actions/socials.ts
new file mode 100644
index 00000000..f79b4ad1
--- /dev/null
+++ b/src/store/actions/socials.ts
@@ -0,0 +1,38 @@
+import {RootState} from '../rootReducer';
+import {loadSocialPosts} from '../../services';
+import {Action, ThunkAction} from '@reduxjs/toolkit';
+import {userSocialsFetched, individualSocialfetched} from '../reducers';
+import {loadAllSocialsForUser} from '../../utils';
+
+export const loadIndividualSocial = (
+ userId: string,
+ socialType: string,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+ dispatch,
+) => {
+ try {
+ const social = await loadSocialPosts(userId, socialType);
+ dispatch({
+ type: individualSocialfetched.type,
+ payload: {socialType, social},
+ });
+ } catch (error) {
+ console.log(error);
+ }
+};
+
+export const loadAllSocials = (
+ userId: string,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+ dispatch,
+) => {
+ try {
+ const socials = await loadAllSocialsForUser(userId);
+ dispatch({
+ type: userSocialsFetched.type,
+ payload: socials,
+ });
+ } catch (error) {
+ console.log(error);
+ }
+};
diff --git a/src/store/actions/taggUsers.ts b/src/store/actions/taggUsers.ts
new file mode 100644
index 00000000..7f841c51
--- /dev/null
+++ b/src/store/actions/taggUsers.ts
@@ -0,0 +1,24 @@
+import {RootState} from '../rootReducer';
+import {loadRecentlySearchedUsers, getAllTaggUsers} from '../../services';
+import {Action, ThunkAction} from '@reduxjs/toolkit';
+import {taggUsersFetched} from '../reducers';
+import {getTokenOrLogout} from '../../utils';
+
+export const loadRecentlySearched = (): ThunkAction<
+ Promise<void>,
+ RootState,
+ unknown,
+ Action<string>
+> => async (dispatch) => {
+ try {
+ const token = await getTokenOrLogout(dispatch);
+ const recentSearches = await loadRecentlySearchedUsers();
+ const taggUsers = await getAllTaggUsers(token);
+ dispatch({
+ type: taggUsersFetched.type,
+ payload: {recentSearches, taggUsers},
+ });
+ } catch (error) {
+ console.log(error);
+ }
+};
diff --git a/src/store/actions/user.ts b/src/store/actions/user.ts
new file mode 100644
index 00000000..09ec8abf
--- /dev/null
+++ b/src/store/actions/user.ts
@@ -0,0 +1,52 @@
+import {RootState} from '../rootReducer';
+import {UserType} from '../../types/types';
+import {loadProfileInfo, loadAvatar, loadCover} from '../../services';
+import {Action, ThunkAction} from '@reduxjs/toolkit';
+import {userLoggedIn, userDetailsFetched} from '../reducers';
+import {getTokenOrLogout} from '../../utils';
+
+/**
+ * Entry point to our store.
+ * Thunk allows us to make async API calls and hence is responsible to fetch data from server.
+ */
+
+/**
+ * Lets understand Thunk.
+ * https://bloggie.io/@_ChristineOo/understanding-typings-of-redux-thunk-action
+ * https://github.com/reduxjs/redux-thunk
+ */
+
+export const loadUserData = (
+ user: UserType,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+ dispatch,
+) => {
+ try {
+ await dispatch({type: userLoggedIn.type, payload: user});
+ const token = await getTokenOrLogout(dispatch);
+ const [profile, avatar, cover] = await Promise.all([
+ loadProfileInfo(token, user.userId),
+ loadAvatar(token, user.userId),
+ loadCover(token, user.userId),
+ ]);
+ dispatch({
+ type: userDetailsFetched.type,
+ payload: {profile, cover, avatar},
+ });
+ } catch (error) {
+ console.log(error);
+ }
+};
+
+export const logout = (): ThunkAction<
+ Promise<void>,
+ RootState,
+ unknown,
+ Action<string>
+> => async (dispatch) => {
+ try {
+ dispatch({type: userLoggedIn.type, payload: {userId: '', username: ''}});
+ } catch (error) {
+ console.log(error);
+ }
+};
diff --git a/src/store/actions/userBlock.ts b/src/store/actions/userBlock.ts
new file mode 100644
index 00000000..f903e99e
--- /dev/null
+++ b/src/store/actions/userBlock.ts
@@ -0,0 +1,48 @@
+import {RootState} from '../rootReducer';
+import {ProfilePreviewType, UserType} from '../../types/types';
+import {blockOrUnblockUser, loadBlockedUsers} from '../../services';
+import {Action, ThunkAction} from '@reduxjs/toolkit';
+import {userBlockFetched, updateBlockedList, userLoggedIn} from '../reducers';
+import {getTokenOrLogout} from '../../utils';
+
+export const loadBlockedList = (
+ userId: string,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+ dispatch,
+) => {
+ try {
+ const token = await getTokenOrLogout(dispatch);
+ const blocked = await loadBlockedUsers(userId, token);
+ dispatch({
+ type: userBlockFetched.type,
+ payload: blocked,
+ });
+ } catch (error) {
+ console.log(error);
+ }
+};
+
+export const blockUnblockUser = (
+ blocker: UserType,
+ blocked: ProfilePreviewType,
+ isBlocked: boolean,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+ dispatch,
+) => {
+ const token = await getTokenOrLogout(dispatch);
+ const success = blockOrUnblockUser(
+ blocker.userId,
+ blocked.id,
+ token,
+ isBlocked,
+ );
+ if (success) {
+ dispatch({
+ type: updateBlockedList.type,
+ payload: {
+ isBlocked,
+ data: blocked,
+ },
+ });
+ }
+};
diff --git a/src/store/actions/userFollow.ts b/src/store/actions/userFollow.ts
new file mode 100644
index 00000000..e23bbfc0
--- /dev/null
+++ b/src/store/actions/userFollow.ts
@@ -0,0 +1,57 @@
+import {getTokenOrLogout} from './../../utils';
+import {RootState} from '../rootReducer';
+import {ProfilePreviewType, UserType} from '../../types/types';
+import {
+ followOrUnfollowUser,
+ loadFollowers,
+ loadFollowing,
+} from '../../services';
+import {Action, ThunkAction} from '@reduxjs/toolkit';
+import {userFollowFetched, updateFollowing, userLoggedIn} from '../reducers';
+
+export const loadFollowData = (
+ userId: string,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+ dispatch,
+) => {
+ try {
+ const token = await getTokenOrLogout(dispatch);
+ const followers = await loadFollowers(userId, token);
+ const following = await loadFollowing(userId, token);
+ dispatch({
+ type: userFollowFetched.type,
+ payload: {followers, following},
+ });
+ } catch (error) {
+ console.log(error);
+ }
+};
+
+export const followUnfollowUser = (
+ follower: UserType,
+ followed: ProfilePreviewType,
+ isFollowed: boolean,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+ dispatch,
+) => {
+ try {
+ const token = await getTokenOrLogout(dispatch);
+ const success = await followOrUnfollowUser(
+ follower.userId,
+ followed.id,
+ token,
+ isFollowed,
+ );
+ if (success) {
+ dispatch({
+ type: updateFollowing.type,
+ payload: {
+ isFollowed,
+ data: followed,
+ },
+ });
+ }
+ } catch (error) {
+ console.log(error);
+ }
+};
diff --git a/src/store/actions/userMoments.ts b/src/store/actions/userMoments.ts
new file mode 100644
index 00000000..dce8da8a
--- /dev/null
+++ b/src/store/actions/userMoments.ts
@@ -0,0 +1,22 @@
+import {RootState} from '../rootReducer';
+import {loadMoments} from '../../services';
+import {Action, ThunkAction} from '@reduxjs/toolkit';
+import {userMomentsFetched} from '../reducers';
+import {getTokenOrLogout} from '../../utils';
+
+export const loadUserMoments = (
+ userId: string,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+ dispatch,
+) => {
+ try {
+ const token = await getTokenOrLogout(dispatch);
+ const moments = await loadMoments(userId, token);
+ dispatch({
+ type: userMomentsFetched.type,
+ payload: moments,
+ });
+ } catch (error) {
+ console.log(error);
+ }
+};
diff --git a/src/store/actions/userX.ts b/src/store/actions/userX.ts
new file mode 100644
index 00000000..5468f762
--- /dev/null
+++ b/src/store/actions/userX.ts
@@ -0,0 +1,131 @@
+import {userXInStore} from './../../utils/';
+import {getTokenOrLogout, loadAllSocialsForUser} from './../../utils';
+import {UserType, ScreenType, ProfilePreviewType} from '../../types/types';
+import {RootState} from '../rootReducer';
+import {Action, ThunkAction} from '@reduxjs/toolkit';
+import {
+ userXRequested,
+ userXAvatarFetched,
+ userXFollowersFetched,
+ userXFollowingFetched,
+ userXCoverFetched,
+ userXMomentsFetched,
+ userXProfileFetched,
+ userXSocialsFetched,
+ userXUserFetched,
+ resetScreen,
+} from '../reducers';
+import {
+ loadProfileInfo,
+ loadAvatar,
+ loadCover,
+ loadFollowers,
+ loadFollowing,
+ loadMoments,
+} from '../../services';
+
+export const loadUserX = (
+ user: UserType,
+ screenType: ScreenType,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+ dispatch,
+) => {
+ try {
+ const {userId} = user;
+ await dispatch({type: userXRequested.type, payload: {screenType, userId}});
+ await dispatch({
+ type: userXUserFetched.type,
+ payload: {screenType, userId, user},
+ });
+ const token = await getTokenOrLogout(dispatch);
+ loadProfileInfo(token, userId).then((data) =>
+ dispatch({
+ type: userXProfileFetched.type,
+ payload: {screenType, userId, data},
+ }),
+ );
+ loadAllSocialsForUser(userId).then((data) =>
+ dispatch({
+ type: userXSocialsFetched.type,
+ payload: {screenType, userId, data},
+ }),
+ );
+ loadAvatar(token, userId).then((data) =>
+ dispatch({
+ type: userXAvatarFetched.type,
+ payload: {screenType, userId, data},
+ }),
+ );
+ loadCover(token, userId).then((data) =>
+ dispatch({
+ type: userXCoverFetched.type,
+ payload: {screenType, userId, data},
+ }),
+ );
+ loadFollowers(userId, token).then((data) =>
+ dispatch({
+ type: userXFollowersFetched.type,
+ payload: {screenType, userId, data},
+ }),
+ );
+ loadFollowing(userId, token).then((data) =>
+ dispatch({
+ type: userXFollowingFetched.type,
+ payload: {screenType, userId, data},
+ }),
+ );
+ loadMoments(userId, token).then((data) =>
+ dispatch({
+ type: userXMomentsFetched.type,
+ payload: {screenType, userId, data},
+ }),
+ );
+ } catch (error) {
+ console.log(error);
+ }
+};
+
+export const updateUserXFollowersAndFollowing = (
+ userId: string,
+ state: RootState,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+ dispatch,
+) => {
+ try {
+ const screens = <ScreenType[]>[ScreenType.Profile, ScreenType.Search];
+ const token = await getTokenOrLogout(dispatch);
+ screens.forEach((screenType) => {
+ if (userXInStore(state, screenType, userId)) {
+ loadFollowers(userId, token).then((data) =>
+ dispatch({
+ type: userXFollowersFetched.type,
+ payload: {screenType, userId, data},
+ }),
+ );
+ loadFollowing(userId, token).then((data) =>
+ dispatch({
+ type: userXFollowingFetched.type,
+ payload: {screenType, userId, data},
+ }),
+ );
+ }
+ });
+ } catch (error) {
+ console.log(error);
+ }
+};
+
+export const resetScreenType = (
+ screenType: ScreenType,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+ dispatch,
+) => {
+ try {
+ dispatch({
+ type: resetScreen.type,
+ payload: {screenType},
+ });
+ } catch (error) {
+ console.log(error);
+ }
+};
diff --git a/src/store/configureStore.ts b/src/store/configureStore.ts
new file mode 100644
index 00000000..7689af5c
--- /dev/null
+++ b/src/store/configureStore.ts
@@ -0,0 +1,20 @@
+import {configureStore, getDefaultMiddleware} from '@reduxjs/toolkit';
+import reducer from './rootReducer';
+
+/**
+ * The entry point to our store
+ * getDefaultMiddleware : This returns an array of default middlewares like Thunk (used for async calls)
+ */
+
+const store = configureStore({
+ reducer,
+ middleware: [...getDefaultMiddleware()],
+});
+
+/**
+ * The exports below come in handy when dispatching from a file outside of any of the Child component's
+ */
+export type AppDispatch = typeof store.dispatch;
+export type GetState = typeof store.getState;
+
+export default store;
diff --git a/src/store/initialStates.ts b/src/store/initialStates.ts
new file mode 100644
index 00000000..4087b97c
--- /dev/null
+++ b/src/store/initialStates.ts
@@ -0,0 +1,95 @@
+import {MomentType} from 'src/types';
+import {
+ ProfileType,
+ SocialAccountType,
+ ProfilePreviewType,
+ ScreenType,
+ UserXType,
+ UserType,
+} from '../types';
+
+export const NO_PROFILE: ProfileType = {
+ biography: '',
+ website: '',
+ name: '',
+ gender: '',
+ birthday: undefined,
+};
+
+export const EMPTY_MOMENTS_LIST = <MomentType[]>[];
+
+export const NO_USER: UserType = {
+ userId: '',
+ username: '',
+};
+
+export const EMPTY_PROFILE_PREVIEW_LIST = <ProfilePreviewType[]>[];
+
+export const NO_USER_DATA = {
+ user: <UserType>NO_USER,
+ profile: <ProfileType>NO_PROFILE,
+ avatar: <string | null>'',
+ cover: <string | null>'',
+};
+
+export const NO_FOLLOW_DATA = {
+ followers: EMPTY_PROFILE_PREVIEW_LIST,
+ following: EMPTY_PROFILE_PREVIEW_LIST,
+};
+
+export const NO_MOMENTS = {
+ moments: EMPTY_MOMENTS_LIST,
+};
+
+export const NO_SOCIAL_ACCOUNTS: Record<string, SocialAccountType> = {
+ Instagram: {posts: []},
+ Facebook: {posts: []},
+ Twitter: {posts: []},
+};
+
+export const NO_TAGG_USERS = {
+ recentSearches: EMPTY_PROFILE_PREVIEW_LIST,
+ taggUsers: EMPTY_PROFILE_PREVIEW_LIST,
+};
+
+export const NO_SOCIALS = {
+ socialAccounts: NO_SOCIAL_ACCOUNTS,
+};
+
+export const NO_BLOCKED_USERS = {
+ blockedUsers: EMPTY_PROFILE_PREVIEW_LIST,
+};
+
+/**
+ * The dummy userId and username serve the purpose of preventing app crash
+ * For instance, if it may happen that data in our store is not loaded yet for the userXId being visited.
+ * Then we will set the userXId / username to this dummy username / userid
+ */
+export const DUMMY_USERID = 'ID-1234-567';
+export const DUMMY_USERNAME = 'tagg_userX';
+
+export const EMPTY_USER_X = <UserXType>{
+ followers: EMPTY_PROFILE_PREVIEW_LIST,
+ following: EMPTY_PROFILE_PREVIEW_LIST,
+ moments: EMPTY_MOMENTS_LIST,
+ socialAccounts: NO_SOCIAL_ACCOUNTS,
+ user: NO_USER,
+ profile: NO_PROFILE,
+ avatar: '',
+ cover: '',
+};
+
+/**
+ * A dummy userX to always be there in out initial app state
+ */
+export const EMPTY_USERX_LIST = <Record<string, UserXType>>{
+ [DUMMY_USERID]: EMPTY_USER_X,
+};
+
+export const EMPTY_SCREEN_TO_USERS_LIST: Record<
+ ScreenType,
+ Record<string, UserXType>
+> = {
+ [ScreenType.Profile]: EMPTY_USERX_LIST,
+ [ScreenType.Search]: EMPTY_USERX_LIST,
+};
diff --git a/src/store/reducers/index.ts b/src/store/reducers/index.ts
new file mode 100644
index 00000000..0e378bc5
--- /dev/null
+++ b/src/store/reducers/index.ts
@@ -0,0 +1,7 @@
+export * from './userFollowReducer';
+export * from './userReducer';
+export * from './userMomentsReducer';
+export * from './userSocialsReducer';
+export * from './taggUsersReducer';
+export * from './userBlockReducer';
+export * from './userXReducer';
diff --git a/src/store/reducers/taggUsersReducer.ts b/src/store/reducers/taggUsersReducer.ts
new file mode 100644
index 00000000..ff30f7a0
--- /dev/null
+++ b/src/store/reducers/taggUsersReducer.ts
@@ -0,0 +1,16 @@
+import {NO_TAGG_USERS} from '../initialStates';
+import {createSlice} from '@reduxjs/toolkit';
+
+const taggUsersSlice = createSlice({
+ name: 'taggUsers',
+ initialState: NO_TAGG_USERS,
+ reducers: {
+ taggUsersFetched: (state, action) => {
+ state.recentSearches = action.payload.taggUsers;
+ state.taggUsers = action.payload.taggUsers;
+ },
+ },
+});
+
+export const {taggUsersFetched} = taggUsersSlice.actions;
+export const taggUsersReducer = taggUsersSlice.reducer;
diff --git a/src/store/reducers/userBlockReducer.ts b/src/store/reducers/userBlockReducer.ts
new file mode 100644
index 00000000..90e4a04a
--- /dev/null
+++ b/src/store/reducers/userBlockReducer.ts
@@ -0,0 +1,25 @@
+import {createSlice} from '@reduxjs/toolkit';
+import {NO_BLOCKED_USERS} from '../initialStates';
+
+const userBlockSlice = createSlice({
+ name: 'userBlock',
+ initialState: NO_BLOCKED_USERS,
+ reducers: {
+ userBlockFetched: (state, action) => {
+ state.blockedUsers = action.payload;
+ },
+
+ updateBlockedList: (state, action) => {
+ const {isBlocked, data} = action.payload;
+ if (!isBlocked) state.blockedUsers.push(data);
+ else {
+ state.blockedUsers = state.blockedUsers.filter(
+ (user) => user.username != data.username,
+ );
+ }
+ },
+ },
+});
+
+export const {userBlockFetched, updateBlockedList} = userBlockSlice.actions;
+export const userBlockReducer = userBlockSlice.reducer;
diff --git a/src/store/reducers/userFollowReducer.ts b/src/store/reducers/userFollowReducer.ts
new file mode 100644
index 00000000..55e16532
--- /dev/null
+++ b/src/store/reducers/userFollowReducer.ts
@@ -0,0 +1,27 @@
+import {createSlice} from '@reduxjs/toolkit';
+import {act} from 'react-test-renderer';
+import {NO_FOLLOW_DATA} from '../initialStates';
+
+const userFollowSlice = createSlice({
+ name: 'userFollow',
+ initialState: NO_FOLLOW_DATA,
+ reducers: {
+ userFollowFetched: (state, action) => {
+ state.followers = action.payload.followers;
+ state.following = action.payload.following;
+ },
+
+ updateFollowing: (state, action) => {
+ const {isFollowed, data} = action.payload;
+ if (!isFollowed) state.following.push(data);
+ else {
+ state.following = state.following.filter(
+ (follow) => follow.username !== data.username,
+ );
+ }
+ },
+ },
+});
+
+export const {userFollowFetched, updateFollowing} = userFollowSlice.actions;
+export const userFollowReducer = userFollowSlice.reducer;
diff --git a/src/store/reducers/userMomentsReducer.ts b/src/store/reducers/userMomentsReducer.ts
new file mode 100644
index 00000000..456ca2fa
--- /dev/null
+++ b/src/store/reducers/userMomentsReducer.ts
@@ -0,0 +1,15 @@
+import {createSlice} from '@reduxjs/toolkit';
+import {NO_MOMENTS} from '../initialStates';
+
+const userMomentsSlice = createSlice({
+ name: 'userMoments',
+ initialState: NO_MOMENTS,
+ reducers: {
+ userMomentsFetched: (state, action) => {
+ state.moments = action.payload;
+ },
+ },
+});
+
+export const {userMomentsFetched} = userMomentsSlice.actions;
+export const userMomentsReducer = userMomentsSlice.reducer;
diff --git a/src/store/reducers/userReducer.ts b/src/store/reducers/userReducer.ts
new file mode 100644
index 00000000..f43bd0bc
--- /dev/null
+++ b/src/store/reducers/userReducer.ts
@@ -0,0 +1,36 @@
+import {createSlice, Action} from '@reduxjs/toolkit';
+import {NO_USER_DATA} from '../initialStates';
+
+/**
+ * A reducer is a pure function with the sole responsibility of updating the state and nothing else.
+ * No side effects are allowed.
+ */
+
+/**
+ * Actions are a way to indicate what just happened / what is going to happen and update the state accordingly.
+ */
+
+/**
+ * Create slice allows us
+ * To initialise State , create Actions and Reducers in one go
+ * Read more here https://redux.js.org/introduction/installation
+ */
+
+const userDataSlice = createSlice({
+ name: 'userData',
+ initialState: NO_USER_DATA,
+ reducers: {
+ userLoggedIn: (state, action) => {
+ state.user = action.payload;
+ },
+
+ userDetailsFetched: (state, action) => {
+ state.profile = action.payload.profile;
+ state.avatar = action.payload.avatar;
+ state.cover = action.payload.cover;
+ },
+ },
+});
+
+export const {userLoggedIn, userDetailsFetched} = userDataSlice.actions;
+export const userDataReducer = userDataSlice.reducer;
diff --git a/src/store/reducers/userSocialsReducer.ts b/src/store/reducers/userSocialsReducer.ts
new file mode 100644
index 00000000..de79568c
--- /dev/null
+++ b/src/store/reducers/userSocialsReducer.ts
@@ -0,0 +1,21 @@
+import {createSlice} from '@reduxjs/toolkit';
+import {NO_SOCIALS} from '../initialStates';
+
+const userSocialsSlice = createSlice({
+ name: 'userSocials',
+ initialState: NO_SOCIALS,
+ reducers: {
+ individualSocialfetched: (state, actions) => {
+ state.socialAccounts[actions.payload.socialType] = actions.payload.social;
+ },
+ userSocialsFetched: (state, action) => {
+ state.socialAccounts = action.payload;
+ },
+ },
+});
+
+export const {
+ userSocialsFetched,
+ individualSocialfetched,
+} = userSocialsSlice.actions;
+export const userSocialsReducer = userSocialsSlice.reducer;
diff --git a/src/store/reducers/userXReducer.ts b/src/store/reducers/userXReducer.ts
new file mode 100644
index 00000000..154dd7dc
--- /dev/null
+++ b/src/store/reducers/userXReducer.ts
@@ -0,0 +1,77 @@
+import {ScreenType} from '../../types/types';
+import {EMPTY_SCREEN_TO_USERS_LIST, EMPTY_USER_X} from '../initialStates';
+import {createSlice} from '@reduxjs/toolkit';
+
+const userXSlice = createSlice({
+ name: 'userX',
+ initialState: EMPTY_SCREEN_TO_USERS_LIST,
+ reducers: {
+ userXRequested: (state, action) => {
+ state[<ScreenType>action.payload.screenType][
+ action.payload.userId
+ ] = EMPTY_USER_X;
+ },
+
+ userXProfileFetched: (state, action) => {
+ state[<ScreenType>action.payload.screenType][
+ action.payload.userId
+ ].profile = action.payload.data;
+ },
+
+ userXUserFetched: (state, action) => {
+ state[<ScreenType>action.payload.screenType][action.payload.userId].user =
+ action.payload.user;
+ },
+
+ userXMomentsFetched: (state, action) => {
+ state[<ScreenType>action.payload.screenType][
+ action.payload.userId
+ ].moments = action.payload.data;
+ },
+ userXFollowersFetched: (state, action) => {
+ state[<ScreenType>action.payload.screenType][
+ action.payload.userId
+ ].followers = action.payload.data;
+ },
+ userXFollowingFetched: (state, action) => {
+ state[<ScreenType>action.payload.screenType][
+ action.payload.userId
+ ].following = action.payload.data;
+ },
+ userXAvatarFetched: (state, action) => {
+ state[<ScreenType>action.payload.screenType][
+ action.payload.userId
+ ].avatar = action.payload.data;
+ },
+ userXCoverFetched: (state, action) => {
+ state[<ScreenType>action.payload.screenType][
+ action.payload.userId
+ ].cover = action.payload.data;
+ },
+ userXSocialsFetched: (state, action) => {
+ state[<ScreenType>action.payload.screenType][
+ action.payload.userId
+ ].socialAccounts = action.payload.data;
+ },
+
+ resetScreen: (state, action) => {
+ for (let userId in state[<ScreenType>action.payload.screenType]) {
+ state[<ScreenType>action.payload.screenType][userId] = EMPTY_USER_X;
+ }
+ },
+ },
+});
+
+export const {
+ userXUserFetched,
+ userXRequested,
+ userXAvatarFetched,
+ userXFollowersFetched,
+ userXFollowingFetched,
+ userXCoverFetched,
+ userXMomentsFetched,
+ userXProfileFetched,
+ userXSocialsFetched,
+ resetScreen,
+} = userXSlice.actions;
+export const userXReducer = userXSlice.reducer;
diff --git a/src/store/rootReducer.ts b/src/store/rootReducer.ts
new file mode 100644
index 00000000..695ed8c7
--- /dev/null
+++ b/src/store/rootReducer.ts
@@ -0,0 +1,30 @@
+import {combineReducers} from 'redux';
+import {
+ userDataReducer,
+ userSocialsReducer,
+ userFollowReducer,
+ userMomentsReducer,
+ taggUsersReducer,
+ userBlockReducer,
+ userXReducer,
+} from './reducers';
+
+/**
+ * Combine all the reducers in our application.
+ */
+
+const rootReducer = combineReducers({
+ user: userDataReducer,
+ follow: userFollowReducer,
+ moments: userMomentsReducer,
+ socialAccounts: userSocialsReducer,
+ taggUsers: taggUsersReducer,
+ blocked: userBlockReducer,
+ userX: userXReducer,
+});
+
+/**
+ * This RootState export is needed when a component subscribes to a slice of the state.
+ */
+export type RootState = ReturnType<typeof rootReducer>;
+export default rootReducer;