Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@typescript-eslint/default-param-last": "off",
"import/prefer-default-export": "off",
"import/no-cycle": "off",
"import/no-extraneous-dependencies": "off",
"react/react-in-jsx-scope": ["off"],
"react/jsx-uses-react": ["off"],
"react/jsx-props-no-spreading": ["warn"],
Expand All @@ -42,7 +43,13 @@
"namedComponents": ["arrow-function", "function-declaration"],
"unnamedComponents": "arrow-function"
}
]
],
"no-param-reassign": ["error", {
"props": true,
"ignorePropertyModificationsFor": [
"state"
]
}]
}
}

Expand Down
12,521 changes: 4,772 additions & 7,749 deletions package-lock.json

Large diffs are not rendered by default.

63 changes: 31 additions & 32 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,28 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"@types/jest": "^24.0.0",
"@types/node": "^14.6.0",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"@types/react-redux": "^7.1.9",
"@types/react-router-dom": "^5.1.5",
"@types/styled-components": "^5.1.2",
"connected-react-router": "^6.8.0",
"history": "4.10.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-redux": "^7.2.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"@reduxjs/toolkit": "^1.9.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@types/jest": "^29.2.5",
"@types/node": "^18.11.18",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.10",
"@types/react-redux": "^7.1.25",
"@types/react-router-dom": "^5.3.3",
"@types/redux-logger": "^3.0.9",
"@types/styled-components": "^5.1.26",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^8.0.5",
"react-router": "^6.6.2",
"react-router-dom": "^6.6.2",
"react-scripts": "5.0.1",
"redux": "^4.0.5",
"redux-devtools-extension": "^2.13.8",
"redux-thunk": "^2.3.0",
"reselect": "^4.0.0",
"styled-components": "^5.1.1",
"typescript": "~4.0.2"
"redux": "^4.2.0",
"reselect": "^4.1.7",
"styled-components": "^5.3.6",
"typescript": "~4.9.4"
},
"scripts": {
"start": "react-scripts start",
Expand All @@ -36,7 +34,7 @@
"format": "prettier --write src/**/*.ts{,x}",
"lint": "eslint src/ --ext .js,.jsx,.ts,.tsx"
},
"homepage": "https://fedorovsky.github.io/code-react-typescript/",
"homepage": "",
"browserslist": {
"production": [
">0.2%",
Expand All @@ -50,18 +48,19 @@
]
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.42.0",
"eslint": "^8.27.0",
"@typescript-eslint/eslint-plugin": "^5.48.1",
"eslint": "^8.32.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^17.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard-with-typescript": "^23.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-n": "^15.5.0",
"eslint-config-prettier": "^8.6.0",
"eslint-config-standard-with-typescript": "^27.0.1",
"eslint-plugin-import": "^2.27.4",
"eslint-plugin-n": "^15.6.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.31.10",
"prettier": "^2.7.1"
"eslint-plugin-react": "^7.32.0",
"prettier": "^2.8.3",
"redux-logger": "^3.0.6"
},
"resolutions": {
"styled-components": "^5"
Expand Down
9 changes: 0 additions & 9 deletions src/App.test.tsx

This file was deleted.

20 changes: 13 additions & 7 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
import * as React from 'react';
import UserList from 'components/UserList';
import { Route, NavLink, Switch } from 'react-router-dom';
import { Route, NavLink, Routes } from 'react-router-dom';
import Home from 'components/routes/Home';
import Users from 'components/routes/Users';

const App: React.FC = () => (
<div>
<div>
<NavLink to="/home" activeStyle={{ color: 'red' }}>
<NavLink
to="/home"
style={({ isActive }) => (isActive ? { color: 'red' } : undefined)}
>
Home
</NavLink>
<NavLink to="/users" activeStyle={{ color: 'red' }}>
<NavLink
to="/users"
style={({ isActive }) => (isActive ? { color: 'red' } : undefined)}
>
Users
</NavLink>
</div>
<div>
<Switch>
<Route path="/home" component={Home} />
<Route path="/users" component={Users} />
</Switch>
<Routes>
<Route path="/home" element={<Home />} />
<Route path="/users" element={<Users />} />
</Routes>
</div>
<UserList />
</div>
Expand Down
7 changes: 7 additions & 0 deletions src/components/ForTesting/ForTesting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as React from 'react';

const ForTesting: React.FC = () => {
return <div>Hello Component</div>;
};

export default ForTesting;
9 changes: 9 additions & 0 deletions src/components/ForTesting/__tests__/ForTesting.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import ForTesting from '../ForTesting';

describe('ForTesting', () => {
test('render', () => {
render(<ForTesting />);
});
});
3 changes: 3 additions & 0 deletions src/components/ForTesting/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import ForTesting from './ForTesting';

export default ForTesting;
15 changes: 11 additions & 4 deletions src/components/UserList/UserList.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import * as React from 'react';
import { useSelector, shallowEqual, useDispatch } from 'react-redux';
import { userListSelector, fetchUserList } from 'store/users/users';
import { userListSelector, fetchUserList } from 'store/slices/usersSlice';
import useAppSelector from 'hooks/useAppSelector';
import useAppDispatch from 'hooks/useAppDispatch';
import { getSecond } from 'store/integration/second';
import { Wrapper } from './UserList.styled';

const UserList: React.FC = () => {
const userList = useSelector(userListSelector, shallowEqual);
const dispatch = useDispatch();
const userList = useAppSelector(userListSelector);
const dispatch = useAppDispatch();

const handleClick = () => dispatch(fetchUserList());
const handleSecond = () => dispatch(getSecond());

return (
<Wrapper>
<button type="button" onClick={handleClick}>
GET USER LIST
</button>

<button type="button" onClick={handleSecond}>
HANDLE SECOND
</button>

<ul>
{userList.map((user) => (
<li key={user.id}>{user.name}</li>
Expand Down
6 changes: 6 additions & 0 deletions src/hooks/useAppDispatch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { useDispatch } from 'react-redux';
import { AppDispatch } from 'store';

export const useAppDispatch = () => useDispatch<AppDispatch>();

export default useAppDispatch;
6 changes: 6 additions & 0 deletions src/hooks/useAppSelector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { TypedUseSelectorHook, useSelector } from 'react-redux';
import type { RootState } from 'store';

const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

export default useAppSelector;
17 changes: 10 additions & 7 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
import React from 'react';
import ReactDOM from 'react-dom';
import ReactDOM from 'react-dom/client';
import { Provider, ReactReduxContext } from 'react-redux';
import { ConnectedRouter } from 'connected-react-router';
import { BrowserRouter } from 'react-router-dom';
import { ThemeProvider } from 'styled-components';
import theme from 'utils/theme';
import store, { history } from './store';
import store from './store';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement,
);

root.render(
<React.StrictMode>
<Provider store={store} context={ReactReduxContext}>
<ConnectedRouter history={history} context={ReactReduxContext}>
<BrowserRouter>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</ConnectedRouter>
</BrowserRouter>
</Provider>
</React.StrictMode>,
document.getElementById('root'),
);

// If you want your app to work offline and load faster, you can change
Expand Down
26 changes: 9 additions & 17 deletions src/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
import { createBrowserHistory } from 'history';
import { composeWithDevTools } from 'redux-devtools-extension';
import { createStore, applyMiddleware } from 'redux';
import { routerMiddleware } from 'connected-react-router';
import thunk from 'redux-thunk';
import { configureStore } from '@reduxjs/toolkit';
import { createLogger } from 'redux-logger';
import rootReducer from './rootReducer';

// browser history
export const history = createBrowserHistory();
const logger = createLogger({
collapsed: true,
});

// compose enhancers
const enhancer = composeWithDevTools(
applyMiddleware(routerMiddleware(history), thunk),
);

// rehydrate state on app start
const initialState = {};

// create store
const store = createStore(rootReducer(history), initialState, enhancer);
const store = configureStore({
reducer: rootReducer(),
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
});

export type RootState = ReturnType<typeof store.getState>;

Expand Down
15 changes: 14 additions & 1 deletion src/store/integration/second.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Reducer } from 'redux';
import { createSelector } from 'reselect';
import { ThunkAction } from '@reduxjs/toolkit';
import { RootState } from '../index';

/**
Expand Down Expand Up @@ -55,4 +56,16 @@ interface SecondRequest {

type ActionType = SecondRequest;

// type ThunkResult<R> = ThunkAction<R, RootState, void, ActionType>;
type ThunkResult<R> = ThunkAction<R, RootState, void, ActionType>;

export const getSecond = (): ThunkResult<void> => {
return (dispatch, getState) => {
console.log('=========');
console.log('dispatch', dispatch);
console.log('getState', getState);
console.log('=========');
dispatch({
type: ACTION.SECOND_REQUEST,
});
};
};
7 changes: 2 additions & 5 deletions src/store/rootReducer.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';
import { History } from 'history';
import { usersReducer } from './users/users';
import usersReducer from './slices/usersSlice';
import { integrationReducer } from './integration';

const rootReducer = (history: History) =>
const rootReducer = () =>
combineReducers({
router: connectRouter(history),
users: usersReducer,
integration: integrationReducer,
});
Expand Down
Loading