I am trying to add the items to a cart page when a user clicks the add to cart button.
import React from "react";
import "bootstrap";
import { useParams } from "react-router-dom";
function ItemDetail(handleClick) {
const params = useParams();
let { productCode, vendor, value} = params;
let item = {productCode, vendor, value};
console.log(item);
return (
<>
<div>
<p>product id: {productCode}</p>
<p>price: {value}</p>
<p>vendor: {vendor}</p>
<button onClick={() => handleClick(item)}>Add to Cart</button>
</div>
</>
);
}
export default ItemDetail;
This is the cart page. Where I am to, render the item details from Item Details Page.
import React, { useState, useEffect } from "react";
const Cart = ({ cart, setCart, handleChange }) => {
const [price, setPrice] = useState(0);
const handleRemove = (id) => {
const arr = cart.filter((item) => item.id !== id);
setCart(arr);
handlePrice();
};
const handlePrice = () => {
let ans = 0;
cart.map((item) => (ans += item.amount * item.price));
setPrice(ans);
};
useEffect(() => {
handlePrice();
});
console.log(setCart);
return (
<article>
{cart.map((item) => (
<div className="cart_box" key={item.id}>
<div>
<button onClick={() => handleChange(item, 1)}>+</button>
<button>{item.amount}</button>
<button onClick={() => handleChange(item, -1)}>-</button>
</div>
<div>
<span>{item.price}</span>
<button onClick={() => handleRemove(item.id)}>Remove</button>
</div>
</div>
))}
<div className="total">
<span>Total Price of your Cart</span>
<span>R - {price}</span>
</div>
</article>
);
};
export default Cart;
This is my item description page. I have fetched the items using params, this is only way I found easier for me.
import React, { useState, useEffect } from "react";
import { Row, Col } from "react-bootstrap";
import StyledCard from "../components/Card";
const Discover = (props, params, handleClick) => {
const token = "not-the-actual-token";
const [result, setResult] = useState([]);
useEffect(() => {
fetch(
"https://api.flash-internal.flash-group.com/ecommerceManagement/1.0.0/api/product/",
{
method: "GET",
headers: { Authorization: `Bearer ${token}` },
}
)
.then((res) => res.json())
.then((json) => setResult(json));
}, []);
const cardStyle = {
listStyle: "none",
margin: 5,
paddingLeft: 0,
minWidth: 240,
};
return (
<>
<div className="latestdeals container my-5">
<h1>All Products</h1>
<Row className="hotcards">
<Col className="colcard">
{(result?.result || []).map((item) => (
<div key={item.productCode} style={cardStyle}>
<a href={`/itemDetail/${item.productCode}/${item.value}/${item.vendor}`}>
{" "}
<StyledCard
key={item.productCode}
name={item.vendor}
title={item.description}
price={item.value}
handleClick={handleClick}
item={item}
/>
</a>
</div>
))}
</Col>
</Row>
</div>
</>
);
};
export default Discover;
This is my App page
import "./index.scss";
import React, { useState } from "react";
import {
BrowserRouter as Router,
Route,
Routes,
useParams,
} from "react-router-dom";
import AllCategories from "./pages/all-catergories";
import Home from "./pages/home";
import Entertainment from "./pages/entertainment";
// import Cart from "./pages/_cart";
import Login from "./pages/login";
import Netflix from "./pages/netflix";
import Orders from "./pages/orders";
import SignUp from "./pages/sign-up";
// import Data2 from "./Data2";
import Products from "./pages/products";
// import Shop from "./components/Shop";
// import ProductDetail from "./pages/ProductDetail";
import Discover from "./pages/discover";
import ItemDetail from "./pages/itemDetail";
import Cart from "./pages/cart";
function App() {
const [show, setShow] = useState(true);
const [cart, setCart] = useState([]);
const handleClick = (item) => {
if (cart.indexOf(item) !== -1) return;
setCart([...cart, item]);
};
const handleChange = (item, d) => {
const ind = cart.indexOf(item);
const arr = cart;
arr[ind].amount += d;
if (arr[ind].amount === 0) arr[ind].amount = 1;
setCart([...arr]);
};
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="all-categories" exact element={<AllCategories />} />
{/* <Route path="cart" exact element={<Cart />} /> */}
<Route path="entertainment" exact element={<Entertainment />} />
<Route path="login" exact element={<Login />} />
<Route path="discover" exact element={<Discover />} />
<Route path="netflix" exact element={<Netflix />} />
<Route path="orders" exact element={<Orders />} />
<Route path="sign-up" exact element={<SignUp />} />
<Route path="products" element={<Products />} />
<Route path="/itemDetail/:productCode/:value/:vendor" element={<ItemDetail />} />
<Route path="/itemDetail/" element={<ItemDetail handleClick={handleClick} />} />
<Route path="/Cart/" exact element={<Cart cart={cart} setCart={setCart} handleChange={handleChange}/>} />
</Routes>
</Router>
);
}
export default App;
Issues
You've issues declaring React components, several of them aren't using props correctly. function ItemDetail(handleClick) { ... } should be function ItemDetail({ handleClick }) { ... }, and const Discover = (props, params, handleClick) => { ... } should probably be something like const Discover = ({ params, handleClick, ...props }) => { ... }. React components receive a single props object argument.
handleChange in App is also mutating state.
Solution
App
Fix the state mutation and ensure props are passed correctly to routed components. Use an item GUID to search the cart instead of shallow reference equality when checking to add to the cart. When updating cart quantities it is necessary to shallow copy the cart array and cart items that are being updated. Use functional state updates whenever possible so it's ensured it's updating from the previous state and not any stale state value closed over in scope.
function App() {
const [show, setShow] = useState(true);
const [cart, setCart] = useState([]);
const handleClick = (item) => {
// Update cart item quantity if already in cart
if (cart.some((cartItem) => cartItem.productCode === item.productCode)) {
setCart((cart) =>
cart.map((cartItem) =>
cartItem.productCode === item.productCode
? {
...cartItem,
amount: cartItem.amount + 1
}
: cartItem
)
);
return;
}
// Add to cart
setCart((cart) => [
...cart,
{ ...item, amount: 1 } // <-- initial amount 1
]);
};
const handleChange = (productCode, d) => {
setCart((cart) =>
cart.flatMap((cartItem) =>
cartItem.productCode === productCode
? cartItem.amount + d < 1
? [] // <-- remove item if amount will be less than 1
: [
{
...cartItem,
amount: cartItem.amount + d
}
]
: [cartItem]
)
);
};
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="all-categories" element={<AllCategories />} />
<Route path="entertainment" element={<Entertainment />} />
<Route path="login" element={<Login />} />
<Route path="discover" element={<Discover />} />
<Route path="netflix" element={<Netflix />} />
<Route path="orders" element={<Orders />} />
<Route path="sign-up" element={<SignUp />} />
<Route path="products" element={<Products />} />
<Route
path="/itemDetail/:productCode/:value/:vendor"
element={<ItemDetail handleClick={handleClick} />}
/>
<Route
path="/Cart/"
element={(
<Cart
cart={cart}
setCart={setCart}
handleChange={handleChange}
/>
)}
/>
</Routes>
</Router>
);
}
ItemDetail
Access/destructure the handleClick prop correctly. Pass the item's productCode to the callback.
function ItemDetail({ handleClick }) {
const { productCode, vendor, value} = useParams();
const item = { productCode, vendor, value };
return (
<div>
<p>product id: {productCode}</p>
<p>price: {value}</p>
<p>vendor: {vendor}</p>
<button onClick={() => handleClick(item)}>Add to Cart</button>
</div>
);
}
Discover
Correctly access/destructure the handleClick callback. Use the Link component instead of the raw anchor (<a />) tag. The anchor tag will reload the app which very likely isn't what you want to happen. Based on the code I suspect you don't actually need this handleClick since the ItemDetail component is passed it and adds to the cart
import { Link } from 'react-router-dom';
const cardStyle = {
listStyle: "none",
margin: 5,
paddingLeft: 0,
minWidth: 240,
};
const Discover = () => {
const token = "not-the-actual-token";
const [result, setResult] = useState([]);
useEffect(() => {
fetch(
"https://api.flash-internal.flash-group.com/ecommerceManagement/1.0.0/api/product/",
{
method: "GET",
headers: { Authorization: `Bearer ${token}` },
}
)
.then((res) => {
if (!res.ok) {
throw new Error('Network response was not OK');
}
return res.json();
})
.then((data) => setResult(data.result))
.catch(error => {
// handle any rejected Promises, errors, etc...
});
}, []);
return (
<div className="latestdeals container my-5">
<h1>All Products</h1>
<Row className="hotcards">
<Col className="colcard">
{result.map((item) => (
<div key={item.productCode} style={cardStyle}>
<Link to={`/itemDetail/${item.productCode}/${item.value}/${item.vendor}`}>
<StyledCard
name={item.vendor}
title={item.description}
price={item.value}
item={item}
/>
</Link>
</div>
))}
</Col>
</Row>
</div>
);
};
Cart
Don't store the cart total in state, it is easily derived from the cart state.
const Cart = ({ cart, setCart, handleChange }) => {
const handleRemove = (productCode) => {
setCart(cart => cart.filter(item => item.productCode !== productCode));
};
const price = cart.reduce((total, item) => total + item.amount * item.price, 0);
return (
<article>
{cart.map((item) => (
<div className="cart_box" key={item.id}>
<div>
<button onClick={() => handleChange(item.productCode, 1)}>+</button>
<button>{item.amount}</button>
<button onClick={() => handleChange(item.productCode, -1)}>-</button>
</div>
<div>
<span>{item.price}</span>
<button onClick={() => handleRemove(item.productCode)}>Remove</button>
</div>
</div>
))}
<div className="total">
<span>Total Price of your Cart</span>
<span>R - {price}</span>
</div>
</article>
);
};
Related
I used react#18, redux, and react-router#6. I have a button add to cart on my product page and I want the product to be added to local storage and I have that product on my Cart page. After clicking on add to cart button I passed to Cart page with id but it shows not found. How can I solve this problem?
app.js :
<BrowserRouter>
<Routes>
<Route path="/" index element={<HomePage />} />
<Route path="/product/:id" element={<ProductPage />} />
<Route path="/cart/:id?" element={<CartPage />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
cartAction.js
export const addToCart = (id) => async (dispatch, getState) => {
const { data } = await axios.get(http://localhost:8000/products/${id});
dispatch({
type: "CART_ADD_ITEM",
payload: {
id: data.id,
title: data.title,
image1: data.image1,
price: data.price,
},
});
localStorage.setItem("cartItems", JSON.stringify(getState().cart.cartItems));
};
store.js
const reducer = combineReducers({
productList: ProductListReducer,
productDetail: ProductDetailReducer,
cart: cartReducer,
});
const cartItemsFromLocalStorage = localStorage.getItem("cartItems")
? JSON.parse(localStorage.getItem("cartItems"))
: [];
const initialState = { cart: { cartItems: cartItemsFromLocalStorage } };
const middleWare = [thunk];
const store = createStore(
reducer,
initialState,
applyMiddleware(...middleWare)
);
cartReducer.js
export const cartReducer = (state = { cartItems: [] }, action) => {
switch (action.type) {
case "CART_ADD_ITEM":
const item = action.payload;
const existingItems = state.cartItems.find(
(i) => i.id === item.id
);
if (existingItems) {
return {
...state,
cartItems: state.cartItems.map((i) =>
i.id === existingItems.id ? item : i
),
};
} else {
return {
...state,
cartItems: [...state.cartItems, item],
};
}
default:
return state;
}
};
cart page:
const CartPage = () => {
const { id } = useParams();
const dispatch = useDispatch();
const cart = useSelector((state) => state.cart);
const { cartItems } = cart;
console.log(cartItems);
useEffect(() => {
if (id) {
dispatch(addToCart(id));
}
}, [dispatch, id]);
const removeCartHandler= (id) => {
dispatch(removeCart(id))
}
return (
<Container>
<Row>
<Col lg="12">
<h1>basket</h1>
{cartItems.length === 0 ? (
<p className="text-center">there is nothing in the basket</p>
) : (
<ListGroup variant="flush">
{cartItems.map((item) => {
return (
<ListGroup.Item key={item.id}>
<CartItems product={item} remove={()=>removeCartHandler(item.id)}/>
</ListGroup.Item>
);
})}
</ListGroup>
)}
</Col>
</Row>
</Container>
);
};
cart Items
const CartItems = ({product}) => {
return (
<Row>
<Col md={2}>
<Image src={product.image1} alt={product.title} fluid />
</Col>
<Col md={3}>{product.title}</Col>
<Col md={2}>{product.price}</Col>
</Row>
product page
const { id } = useParams();
const navigate = useNavigate();
const addToCartHandler = () => {
navigate(/cart/${id});
};
<Button className="btn btn-default" onClick={addToCartHandler}>
<i className="fa fa-shopping-cart"></i> Add to cart
</Button>
Remove the trailing "?" from the cart path. react-router-dom#6 Route components don't take optional parameter or use regular expressions in the path prop.
Change path="/cart/:id?" to path="/cart/:id".
<BrowserRouter>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/product/:id" element={<ProductPage />} />
<Route path="/cart/:id" element={<CartPage />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
I'm building an e-commerce application and for some reason my buttons to update the cart aren't working. I'm using props and when I go to the console log it says that onUpdateCartQty is not a function. I know props are a bit tricky.
Can someone point out what I did wrong?
CartItem.jsx
import React from 'react';
import { Typography, Button, Card, CardActions, CardContent, CardMedia } from '#material-ui/core';
import useStyles from './styles';
const CartItem = ({ item, onUpdateCartQty, onRemoveFromCart }) => {
const classes = useStyles();
return (
//product.image.url?
<Card>
<CardMedia image={item.image.url} alt={item.name} className={classes.media} />
<CardContent className={classes.cardContent}>
<Typography variant="h4">{item.name}</Typography>
<Typography variant="h5">{item.line_total.formatted_with_symbol}</Typography>
</CardContent>
<CardActions className={classes.cardActions}>
<div className={classes.buttons}>
<Button type="button" size= "small" onClick={() => onUpdateCartQty(item.id, item.quantity - 1)}>-</Button>
<Typography>{item.quantity}</Typography>
<Button type="button" size= "small" onClick={() => onUpdateCartQty(item.id, item.quantity + 1)}>+</Button>
</div>
<Button variant="contained" type= "button" color="secondary" onClick={() => onRemoveFromCart(item.id) }>Remove</Button>
</CardActions >
</Card>
)
}
export default CartItem
App.js
import React, { useState, useEffect } from "react";
import { commerce } from './lib/commerce';
import { Products, Navbar, Cart } from './components';
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
const App = () => {
const [products, setProducts] = useState([]);
const [cart, setCart] = useState({});
const fetchProducts = async () => {
const { data } = await commerce.products.list();
setProducts(data);
}
const fetchCart = async () => {
setCart(await commerce.cart.retrieve())
}
const handleAddToCart = async (productId, quantity) => {
const { cart } = await commerce.cart.add(productId, quantity);
setCart(cart);
}
const handleUpdateCartQty = async (productId, quantity) => {
const { cart } = await commerce.cart.update(productId, { quantity});
setCart(cart);
}
const handleEmptyCart = async () => {
const { cart } = await commerce.cart.empty();
setCart(cart);
}
const handleRemoveFromCart = async (productId) => {
const { cart } = await commerce.cart.remove(productId);
setCart(cart);
}
useEffect(() =>{
fetchProducts();
fetchCart();
}, []);
console.log(cart);
return (
<Router>
<div>
<Navbar totalItems={cart.total_items} />
<Routes>
<Route path= "/" element={<Products products = {products} onAddToCart=
{handleAddToCart}/>}/>
{/* <Products products={products} onAddToCart={handleAddToCart} /> */}
{/* </Route> */}
<Route path= "/cart" element= {<Cart cart={cart}/>}
handleUpdateCartQty ={handleUpdateCartQty}
handleRemoveFromCart ={handleRemoveFromCart}
handleEmptyCart ={handleEmptyCart}
/>
{/* <Cart cart={cart} /> */}
{/* </Route> */}
</Routes>
</div>
</Router>
);
};
export default App;
enter image description here
Currently, you are passing props to Route component not CartItem component.
<Route path= "/cart" element= {<Cart cart={cart}/>}
handleUpdateCartQty ={handleUpdateCartQty}
handleRemoveFromCart ={handleRemoveFromCart}
handleEmptyCart ={handleEmptyCart}
/>
Try to send as
<Route path= "/cart" element= {<Cart cart={cart}
handleUpdateCartQty ={handleUpdateCartQty}
handleRemoveFromCart ={handleRemoveFromCart}
handleEmptyCart ={handleEmptyCart}
/>} />
I got my current website displaying hard coded data from my data.js file. I implemented firebase as my database and I want to have my categories button work with the firbase database. FYI, I'm fairly new to developing websites and apps. I'm going to attach my app.js and categories.js file.
Here is my code so far.
const allCategories = ["all", ...new Set(items.map((item) => item.category))];
const MenuApp = () => {
const [menuItems, setMenuItems] = useState(items);
const [activeCategory, setActiveCategory] = useState("");
const [categories, setCategories] = useState(allCategories);
const filterItems = (category) => {
setActiveCategory(category);
if (category === "all") {
setMenuItems(items);
return;
}
const newItems = items.filter((item) => item.category === category);
setMenuItems(newItems);
};
return (
<main>
<section className="menu section">
<div className="title">
<img src={logo} className="logo" />
<h2>Menu List</h2>
<div className="underline"></div>
</div>
<Categories
categories={categories}
activeCategory={activeCategory}
filterItems={filterItems}
/>
<Menu items={menuItems} />
</section>
</main>
);
}
export default App;
const Categories = ({ categories, filterItems, activeCategory }) => {
return (
<div className="btn-container">
{categories.map((category, index) => {
return (
<button
type="button"
className={`${
activeCategory === category ? "filter-btn active" : "filter-btn"
}`}
key={index}
onClick={() => filterItems(category)}
>
{category}
</button>
);
})}
</div>
);
};
export default Categories;
I attched screenshots of how my menu page looks like.
here is how I would do it
import React, { useState } from "react";
import Home from "./Home";
import Navigation from './Navigation';
import {BrowserRouter, Route, Routes, Link } from 'react-router-dom';
import About from './About';
import Fire from './firebase/firebase-test'
import FireMenu from './firebase/firebase-menu'
import Menu from './Menu';
import items from "./data";
import Categories from "./Categories";
import { Full_Menu } from "./firebase/firebaseConfig";
import logo from "./img/logo.jpg"; // this could be a placeholder until we get their official logo
function App () {
return (
<BrowserRouter>
<div className="App">
<Navigation />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/menu" element={<MenuApp />} />
<Route path= "/fire" element={<Fire />}/>
<Route path="/firemenu" element={<FireMenu />}/>
</Routes>
</div>
</BrowserRouter>
);
}
const allCategories = ["all", ...new Set(items.map((item) => item.category))];
const MenuApp = () => {
const [menuItems, setMenuItems] = useState(items)
const [activeCategory, setActiveCategory] = useState("all");
const filterItems = items?.filter(item => {
switch (activeCategory) {
case 'all':
return true
case 'all day specials':
case 'appetizers':
case 'add ins':
return item.category === activeCategory
default:
return true
}
})
return (
<main>
<section className="menu section">
<div className="title">
<h2>Menu List</h2>
<div className="underline"></div>
</div>
<Categories
setActiveCategory={setActiveCategory}
activeCategory={activeCategory}
/>
<Menu items={filterItems} />
</section>
</main>
);
};
export default App;
import React from "react";
const allCategories = ['all','all day specials','appetizers','seafood platter', 'add ins', 'beef', 'chicken', 'chow mein', 'combinations', 'deep fried goodiness', 'dessert', 'fried rice',
'pork', 'seafood platter', 'sides', 'vegetable', 'whats cooking', 'wing']
const Categories = ({ activeCategory, setActiveCategory, }) => {
return (
<div className="btn-container">
{allCategories.map((category, index) => {
return (
<button
type="button"
className={`${
activeCategory === category ? "filter-btn active" : "filter-btn"
}`}
key={index}
onClick={() => setActiveCategory(category)}
>
{category}
</button>
);
})}
</div>
);
};
export default Categories;
I'm building a shopping cart app and I want to prevent an item from appearing on the cart page twice if there's a duplicate. I'm trying to check an array of items objects from the useState hook. If the array contains an object with the item name, I want to prevent it from being added twice, otherwise I want to push it into the array. But when I console log the array, it doesn't update right away. Also, after I hit the "addItemToCart" button on ProductsDetails.jsx twice, I get an error "TypeError: Cannot read property 'find' of undefined." Sorry if I'm not explaining it clearly. Here's my code. Any help would be appreciated.
App.js
function App() {
const [cartItems, setCartItems] = useState([]);
const [cartCount, setCartCount] = useState(0);
const [cartTotal, setCartTotal] = useState(0.00);
return (
<div className="App">
<BrowserRouter>
<NavigationBar count={cartCount} />
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/products" component={ProductsPage} />
<Route exact path="/about" component={AboutPage} />
<Route exact path="/profile" component={ProfilePage} />
<Route
exact
path="/cart"
render={() => {
return (
<CartPage
setCartCount={setCartCount}
cartItems={cartItems}
cartTotal={cartTotal}
cartCount={cartCount}
/>
);
}}
/>
<Route
exact
path="/:details"
render={() => (
<ProductDetails
cartItems={cartItems}
setCartItems={setCartItems}
setCartCount={setCartCount}
setCartTotal={setCartTotal}
/>
)}
/>
</Switch>
</BrowserRouter>
</div>
);
}
export default App;
ProductsDetails.jsx
import React from "react";
import "./ProductDetails.css";
import { useLocation } from "react-router-dom";
const ProductDetails = (props) => {
const location = useLocation();
const products = JSON.parse(localStorage.getItem("data"));
const productInfo = products.find(
(item) => item.name === location.state.name
);
const { name, image, price } = productInfo;
const cartCounter = (counter) => {
props.setCartCount((counter += 1));
};
const cartPriceCounter = (counter) => {
props.setCartTotal((counter += price));
};
const addItemToCart = () => {
const product = {
name,
price,
};
if(!props.cartItems.find(e => e.name === product.name)){
props.setCartItems([...props.cartItems, product]);
}
console.log(props.cartItems)
};
return (
<div className="details-container">
<div className="details-card">
<img className="details-img" src={image} alt={name} />
<div className="details-div">
<h3 className="details-title">{name}</h3>
<p className="details-price">${price}</p>
<button
className="add-to-cart"
onClick={() => {
props.setCartCount(cartCounter);
props.setCartTotal(cartPriceCounter);
props.setCartItems(addItemToCart);
}}
>
Add To Cart
</button>
</div>
</div>
</div>
);
};
export default ProductDetails;
The mutated state won't be reflected in the same render(i.e. in console.log), it would be updated when the next render occurs due to state change
See https://medium.com/ableneo/react-setstate-does-not-immediately-update-the-state-84dbd26f67d5
You could use setState with function argument which would have the updated value.
I want to add to a state array, but I find that any code I write that brings up the state leads to the same error one the browser tries to run it.
Even just a console.log triggers it.
var folderList = this.state.folders;
console.log("folderList: " + folderList);
The full code:
import React, {Component} from 'react';
import {Route, Link} from 'react-router-dom';
import {FontAwesomeIcon} from '#fortawesome/react-fontawesome';
import NoteListNav from '../NoteListNav/NoteListNav';
import NotePageNav from '../NotePageNav/NotePageNav';
import NoteListMain from '../NoteListMain/NoteListMain';
import NotePageMain from '../NotePageMain/NotePageMain';
import dummyStore from '../dummy-store';
import {getNotesForFolder, findNote, findFolder} from '../notes-helpers';
import './App.css';
import AddFolder from '../AddFolder/AddFolder';
import AddNote from '../AddNote/AddNote';
class App extends Component {
state = {
notes: [],
folders: [],
//noteID: 0,
//folderID: 0
};
componentDidMount() {
// fake date loading from API call
setTimeout(() => this.setState(dummyStore), 600);
}
folderSubmit(f){
console.log("folderSubmit ran " + f);
var folderList = this.state.folders;
console.log("folderList: " + folderList);
//this.setState({ folders: joined })
}
renderNavRoutes() {
const {notes, folders} = this.state;
return (
<>
{['/', '/folder/:folderId'].map(path => (
<Route
exact
key={path}
path={path}
render={routeProps => (
<NoteListNav
folders={folders}
notes={notes}
{...routeProps}
/>
)}
/>
))}
<Route
path="/note/:noteId"
render={routeProps => {
const {noteId} = routeProps.match.params;
const note = findNote(notes, noteId) || {};
const folder = findFolder(folders, note.folderId);
return <NotePageNav {...routeProps} folder={folder} />;
}}
/>
<Route path="/add-folder" component={NotePageNav} />
<Route path="/add-note" component={NotePageNav} />
</>
);
}
renderMainRoutes() {
const {notes, folders} = this.state;
return (
<>
{['/', '/folder/:folderId'].map(path => (
<Route
exact
key={path}
path={path}
render={routeProps => {
const {folderId} = routeProps.match.params;
const notesForFolder = getNotesForFolder(
notes,
folderId
);
return (
<NoteListMain
{...routeProps}
notes={notesForFolder}
/>
);
}}
/>
))}
<Route
path="/note/:noteId"
render={routeProps => {
const {noteId} = routeProps.match.params;
const note = findNote(notes, noteId);
return <NotePageMain {...routeProps} note={note} />;
}}
/>
<Route
path="/add-folder"
render={routeProps => {
return <AddFolder addNewFolder={this.folderSubmit}/>
}}
/>
<Route
path="/add-note"
render={routeProps => {
return <AddNote/>
}}
/>
</>
);
}
render() {
return (
<div className="App">
<nav className="App__nav">{this.renderNavRoutes()}</nav>
<header className="App__header">
<h1>
<Link to="/">Noteful</Link>{' '}
<FontAwesomeIcon icon="check-double" />
</h1>
</header>
<main className="App__main">{this.renderMainRoutes()}</main>
</div>
);
}
}
export default App;
this will not be what you expect inside of folderSubmit. How to get around this is discussed in the "Handling Events" part of the documentation. You could bind it to this in the constructor, or use an arrow function as a class field.
folderSubmit = (f) => {
var folderList = this.state.folders;
console.log("folderList:", folderList);
}