Skip to content

Commit

Permalink
add a redux store and a User entity
Browse files Browse the repository at this point in the history
  • Loading branch information
stasguma committed Mar 11, 2024
1 parent 9af9adb commit 514adb5
Show file tree
Hide file tree
Showing 17 changed files with 233 additions and 22 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"@types/node": "^20.10.8",
"@types/react": "^18.2.47",
"@types/react-dom": "^18.2.18",
"@types/react-redux": "^7.1.33",
"@types/react-router-dom": "^5.3.3",
"@types/webpack": "^5.28.5",
"@types/webpack-bundle-analyzer": "^4.6.3",
Expand Down Expand Up @@ -96,12 +97,14 @@
"webpack-dev-server": "^4.15.1"
},
"dependencies": {
"@reduxjs/toolkit": "^2.2.1",
"i18next": "^23.7.18",
"i18next-browser-languagedetector": "^7.2.0",
"i18next-http-backend": "^2.4.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^14.0.1",
"react-redux": "^9.1.0",
"react-router-dom": "^6.21.2"
}
}
114 changes: 110 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/app/providers/StoreProvider/config/StateSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { UserSchema } from '@/entities/User';

export interface StateSchema {
users: UserSchema;
}
7 changes: 7 additions & 0 deletions src/app/providers/StoreProvider/config/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { TypedUseSelectorHook } from 'react-redux';
import type { RootState, AppDispatch } from './store';
import { useDispatch, useSelector } from 'react-redux';

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
16 changes: 16 additions & 0 deletions src/app/providers/StoreProvider/config/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { combineReducers, configureStore } from '@reduxjs/toolkit';

import { userReducer } from '@/entities/User';

export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof rootReducer>;

const rootReducer = combineReducers({
users: userReducer,
});

export const store = configureStore({
reducer: rootReducer,
devTools: __IS_DEV__,
// middleware: () => new Tuple(/* place middleware here */),
});
3 changes: 3 additions & 0 deletions src/app/providers/StoreProvider/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { StoreProvider } from './ui/StoreProvider';
export { store, type RootState, type AppDispatch } from './config/store';
export { useAppDispatch, useAppSelector } from './config/hooks';
16 changes: 16 additions & 0 deletions src/app/providers/StoreProvider/ui/StoreProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { ReactNode, FC } from 'react';
import { Provider } from 'react-redux';

import { store } from '../config/store';
import type { StateSchema } from '../config/StateSchema';

interface IProps {
children: ReactNode;
initialState?: StateSchema;
}

export const StoreProvider: FC<IProps> = ({ children }) => {
return (
<Provider store={store}>{children}</Provider>
);
};
3 changes: 3 additions & 0 deletions src/entities/User/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as userReducer, changeName } from './model/slice/userSlice';
export { type UserSchema } from './model/types/userSchema';
export { getUserName } from './model/selectors/getUserName/getUserName';
Empty file.
6 changes: 6 additions & 0 deletions src/entities/User/model/selectors/getUserName/getUserName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { RootState } from '@/app/providers/StoreProvider';
// import { createSelector } from '@reduxjs/toolkit';

export const getUserName = (state: RootState) => state.users.name;

// createSelector(getUserName, (name) => name);
22 changes: 22 additions & 0 deletions src/entities/User/model/slice/userSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { PayloadAction } from '@reduxjs/toolkit';
import { type UserSchema } from '../types/userSchema';
import { createSlice } from '@reduxjs/toolkit';

// Define the initial state using that type
const initialState: UserSchema = {
name: 'Stas',
};

export const usersSlice = createSlice({
name: 'users',
initialState,
reducers: {
changeName: (state, action: PayloadAction<string>) => {
state.name = action.payload;
},
},
});

export const { changeName } = usersSlice.actions;

export default usersSlice.reducer;
3 changes: 3 additions & 0 deletions src/entities/User/model/types/userSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface UserSchema {
name: string;
}
15 changes: 9 additions & 6 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ import '@/app/styles/index.scss';
import '@/shared/config/i18n/i18n';

import App from '@/app/App';
import { ThemeProvider } from '@/app/providers/ThemeProvider';
import { StoreProvider } from '@/app/providers/StoreProvider';
import { ErrorBoundary } from '@/app/providers/ErrorBoundary';
import { ThemeProvider } from '@/app/providers/ThemeProvider';
import { PageError } from '@/widgets/PageError';

createRoot(document.getElementById('root') as HTMLElement).render(
<StrictMode>
<ErrorBoundary fallback={<PageError />}>
<ThemeProvider>
<App />
</ThemeProvider>
</ErrorBoundary>
<StoreProvider>
<ErrorBoundary fallback={<PageError />}>
<ThemeProvider>
<App />
</ThemeProvider>
</ErrorBoundary>
</StoreProvider>
</StrictMode>
);
13 changes: 13 additions & 0 deletions src/pages/HomePage/ui/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import { type FC } from 'react';
import { useTranslation } from 'react-i18next';

import { useAppDispatch, useAppSelector } from '@/app/providers/StoreProvider';
import { Button } from '@/shared/ui';
import { changeName } from '@/entities/User';

const HomePage: FC = () => {
const { t } = useTranslation();
const userName = useAppSelector(state => state.users.name);
const dispatch = useAppDispatch();

const changeNameHandler = () => {
dispatch(changeName('SuperStas'));
};

return (
<>
{/* eslint-disable-next-line */}
<Button variant="filled" onClick={changeNameHandler}>Change user name</Button>
<p>{userName}</p>
<h1>{t('home')}</h1>
<h2>{t('home')}</h2>
<h3>{t('home')}</h3>
Expand Down
Loading

0 comments on commit 514adb5

Please sign in to comment.