Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Redux #3

Merged
merged 8 commits into from
Jul 27, 2023
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
32 changes: 21 additions & 11 deletions src/components/Book.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
/* eslint-disable no-unused-vars */
import React from 'react';
import PropTypes from 'prop-types';
import Button from './Button';
import { useDispatch } from 'react-redux';
import { RemoveBook } from '../redux/book/bookSlice';

const Book = ({ title, author }) => (
<div>
<h3>{title}</h3>
<p>
By
{author}
</p>
<Button name="Remove" />
</div>
);
const Book = ({ id, title, author }) => {
const dispatch = useDispatch();

const handleRemove = (id) => {
dispatch(RemoveBook(id));
};

return (
<div className="border-b-4">
<h3>{title}</h3>
<p>
By
{author}
</p>
<button type="button" className="px-3 py-1 bg-red-400" onClick={() => handleRemove(id)}> Remove Book </button>
</div>
);
};

Book.propTypes = {
title: PropTypes.string,
author: PropTypes.string,
id: PropTypes.string.isRequired,
};

Book.defaultProps = {
Expand Down
9 changes: 4 additions & 5 deletions src/components/Books.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import React from 'react';
import { useSelector } from 'react-redux';
import Book from './Book';
import Form from './Form';

const Books = () => {
const books = [
{ id: 1, title: 'Book 1', author: 'Author 1' },
{ id: 2, title: 'Book 2', author: 'Author 2' },
];
const { books } = useSelector((state) => state.book);

return (
<div>
{books.map((book) => (
<Book key={book.id} title={book.title} author={book.author} />
<Book key={book.item_id} id={book.item_id} title={book.title} author={book.author} />
))}
<Form />
</div>
Expand Down
6 changes: 5 additions & 1 deletion src/components/Button.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';

const Button = ({ name }) => <button type="button">{name}</button>;
const Button = ({ name }) => (
<button type="button">
{name}
</button>
);

Button.propTypes = {
name: PropTypes.string,
Expand Down
66 changes: 55 additions & 11 deletions src/components/Form.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,57 @@
import React from 'react';
import Button from './Button';

const Form = () => (
<form>
<h3>ADD NEW BOOK</h3>
<input type="text" placeholder="Book title" />
<input type="text" placeholder="Author" />
<Button name="Submit" />
</form>
);
import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { toast } from 'react-toastify';
import { AddBook } from '../redux/book/bookSlice';

const Form = () => {
const { books } = useSelector((state) => state.book);
const dispatch = useDispatch();
const [author, setAuthor] = useState('');
const [title, setTitle] = useState('');

const handleSubmit = (e) => {
e.preventDefault();
if (title.trim() === '' || author.trim() === '') {
toast.error('All fileds must be completed');
return null;
}

dispatch(
AddBook({
item_id: `item${books.length + 1}`,
author,
title,
}),

);
setAuthor('');
setTitle('');

return null;
};

return (
<form className="flex flex-col gap-2" onSubmit={handleSubmit}>
<h3>ADD NEW BOOK</h3>
<input
type="text"
placeholder="Book title"
className="border outline-none border-blue-300"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<input
type="text"
placeholder="Author"
className="border outline-none border-blue-300"
value={author}
onChange={(e) => setAuthor(e.target.value)}
/>
<button type="submit" className="px-3 py-1 bg-blue-700 text-white mx-4 rounded-md">
Add book
</button>
</form>
);
};

export default Form;
6 changes: 5 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { Provider } from 'react-redux';
import App from './App';
import store from './redux/store';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
);
31 changes: 26 additions & 5 deletions src/redux/book/bookSlice.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
import { createReducer } from '@reduxjs/toolkit';

const initialState = {
books: [],
books: [
{
item_id: 'item1',
title: 'The Great Gatsby',
author: 'John Smith',
category: 'Fiction',
},
{
item_id: 'item2',
title: 'Anna Karenina',
author: 'Leo Tolstoy',
category: 'Fiction',
},
{
item_id: 'item3',
title: 'The Selfish Gene',
author: 'Richard Dawkins',
category: 'Nonfiction',
},
],
};

// Reducers
Expand All @@ -10,21 +29,23 @@ export const bookReducer = createReducer(initialState, {
state.books.push(action.payload);
},
remove: (state, action) => {
const { id } = action.payload;
const newState = state.books.filter((i) => i.id !== id);
const id = action.payload;
const newState = state.books.filter((i) => i.item_id !== id);
state.books = newState;
},
});

// Actions
export const AddBook = (dispatch) => {
export const AddBook = (book) => (dispatch) => {
dispatch({
type: 'add',
payload: book,
});
};

export const RemoveBook = (dispatch) => {
export const RemoveBook = (id) => (dispatch) => {
dispatch({
type: 'remove',
payload: id,
});
};
3 changes: 1 addition & 2 deletions src/redux/category/categorySlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ const initialState = {
};

// Reducers
export const categoriesReducer = createReducer({
initialState,
export const categoriesReducer = createReducer(initialState, {
checkstatus: (state) => ({ ...state, status: 'Under Construction' }),
});

Expand Down