Skip to content

Commit

Permalink
Merge pull request #2 from arturparkhisenko/add-redux-tool-kit-example
Browse files Browse the repository at this point in the history
Add Redux Tool Kit example
  • Loading branch information
arturparkhisenko authored Apr 22, 2022
2 parents 6fe7ddf + 3630c5a commit a99c49a
Show file tree
Hide file tree
Showing 49 changed files with 790 additions and 232 deletions.
2 changes: 1 addition & 1 deletion javascript/.eslintrc → javascript/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
],
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2020
"ecmaVersion": 2021
},
"env": {
"node": true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
{
"extends": [
"eslint:recommended",
"plugin:react/recommended"
],
"plugins": [
"react"
"plugin:react/recommended",
"react-app",
"react-app/jest"
],
"plugins": ["react"],
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2018,
"ecmaVersion": 2021,
"ecmaFeatures": {
"jsx": true,
"experimentalObjectRestSpread": true
"jsx": true
}
},
"env": {
Expand Down
43 changes: 25 additions & 18 deletions javascript/frameworks-libraries/react-redux-stack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,35 @@
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom"
"test": "react-scripts test"
},
"dependencies": {
"@reduxjs/toolkit": "^1.8.1",
"normalize.css": "^8.0.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-redux": "^7.2.2",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"reselect": "^4.0.0",
"styled-components": "^5.2.1",
"why-did-you-update": "^1.0.8"
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-redux": "^8.0.1",
"styled-components": "^5.3.5"
},
"devDependencies": {
"eslint": "7.17.0",
"eslint-plugin-react": "^7.22.0",
"react-scripts": "^4.0.1"
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1.1",
"@testing-library/user-event": "^14.1.1",
"eslint": "^8.13.0",
"eslint-plugin-react": "^7.29.4",
"react-scripts": "^5.0.1",
"why-did-you-update": "^1.0.8"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { Component } from 'react';
import { Provider } from 'react-redux';

import Chat from './containers/Chat';
// import Button from './components/Button';
// import ButtonFunctional from './components/ButtonFunctional';
import { store } from './model/store';

window.store = store;
// store.subscribe(() => console.log('subscribe', store.getState()));
// TODO: @see https://redux-toolkit.js.org/api/createListenerMiddleware

export default class App extends Component {
render() {
return (
<Provider store={store}>
<Chat />
{/* <Button text="Usual Button" /> */}
{/* <ButtonFunctional text="ButtonFunctional" /> */}
</Provider>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { render, screen } from '@testing-library/react';
import App from './App';

test('renders without crashing', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';

class Button extends React.Component {
render() {
return (
<button onClick={this.props.onClick}>
{this.props.text}
</button>
);
}
}

export default Button;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';

const ButtonFunctional = ({text, onClick}) => (
<button onClick={onClick}>
{text}
</button>
);

export default ButtonFunctional;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import styled from 'styled-components';

export default styled.h5`
margin: 0 0 1em;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { PureComponent } from 'react';
// Components ---------------------------
import Ul from './Ul';
import Heading5 from './Heading5';
// Styles -------------------------------
import styled from 'styled-components';

const Form = styled.form`
padding: 0.5em;
`;

const Info = styled.span`
opacity: 0.5;
`;

class Messages extends PureComponent {
submitForm(event) {
event.preventDefault();
console.log(this.input.value);
this.props.addMessage(this.input.value, '1');
this.input.value = '';
}

render() {
console.log('Messages props', this.props); // {users}
return (
<Form onSubmit={this.submitForm.bind(this)}>
<Heading5>Messages:</Heading5>
<Ul>
{this.props.messages.map((message) => {
const time = new Date(message.timeStamp);
const hours = time.getHours();
const minutes = time.getMinutes();
return (
<li key={message.timeStamp}>
<Info>{`${hours}:${minutes} ${message.author} `}</Info>
{message.text}
</li>
);
})}
</Ul>
<hr />

<input
ref={(input) => (this.input = input)}
type="text"
placeholder="Enter a message"
/>
</Form>
);
}
}

export default Messages;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import styled from 'styled-components';

export default styled.ul`
padding: 0;
list-style: none;
height: 200px;
overflow: auto;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, {Component} from 'react';
// Components ---------------------------
import Ul from './Ul';
// Styles -------------------------------
import styled from 'styled-components';

const Li = styled.li`
width: 60px;
overflow: hidden;
text-overflow: ellipsis;
`;

const UlStyled = styled(Ul)`
font-family: monospace;
`;

class UserList extends Component {
render() {
console.log('UserList props', this.props); // {users}
return (
<Ul className="UserList">
<UlStyled className="UserList">
{this.props.users.map(user => {
return <Li key={user}>{user}</Li>;
})}
</UlStyled>
</Ul>
);
}
}

export default UserList;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import styled from 'styled-components';

import Messages from './../components/Messages';
import Users from './../containers/Users';
import { chatSelector } from './../model/selectors';
import { addMessage } from './../model/messagesSlice';
import { changeUser } from './../model/actions';

const Content = styled.div`
display: flex;
flex-direction: column;
`;

const Panels = styled.div`
display: flex;
background-color: #f5f5f5;
padding: 0.5em;
`;

class Chat extends Component {
render() {
console.log('Chat props', this.props);
return (
<Content>
<h3>Chat</h3>

<Panels>
<Users addUser={this.props.addUser} users={this.props.users} />
<Messages
addMessage={this.props.addMessage}
messages={this.props.messages}
/>
</Panels>
</Content>
);
}
}

// used a selector below
// const mapStateToProps = state => {
// return {
// users: state.users,
// messages: state.messages
// };
// };

const mapDispatchToProps = { addUser: changeUser, addMessage };

// usual
//export default connect(mapStateToProps, mapDispatchToProps)(Chat);

// with reselect
export default connect(chatSelector, mapDispatchToProps)(Chat);
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, {Component} from 'react';
// Components ---------------------------
import UserList from './../components/UserList';
import Heading5 from './../components/Heading5';
// Styles -------------------------------
import styled from 'styled-components';

const Content = styled.div`
display: flex;
flex-direction: column;
padding: 0.5em;
background-color: #cccdff;
`;

class Users extends Component {
render() {
console.log('Users props', this.props); // {users}
return (
<Content>
<Heading5>Users:</Heading5>
<button onClick={this.props.addUser}>add</button>
<UserList users={this.props.users}/>
</Content>
);
}
}

export default Users;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
body {
font-family: "Century Gothic", Futura, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

#root {
flex-grow: 1;
flex-shrink: 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import { createRoot } from 'react-dom/client';
// Components ---------------------------
import App from './App';
// Styles -------------------------------
import 'normalize.css';
import './index.css';
// --------------------------------------
const root = createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Loading

0 comments on commit a99c49a

Please sign in to comment.