I'm React Beginner.I trying to convert my React code written using class into function or React Hooks. Here is my code
import React, { Component, useState } from "react";
import { Badge, Card, Col, ListGroup, Row } from "react-bootstrap";
import { numberWithCommas } from "../utils/utils";
import Keranjang from "./Keranjang";
import TotalBayar from "./TotalBayar";
import { API_URL } from "../utils/constants";
import axios from "axios";
import swal from "sweetalert";
export default function Hasil(props) {
const [showModal, setShowModal] = useState(false);
const [keranjangDetail, setKeranjangDetail] = useState(false);
const [jumlah, setJumlah] = useState(0);
const [keterangan, setKeterangan] = useState("");
const [totalHarga, setTotalHarga] = useState(0);
const handleShow = (menuKeranjang) => {
setShowModal(true);
setKeranjangDetail(menuKeranjang);
setJumlah(menuKeranjang.jumlah);
setKeterangan(menuKeranjang.keterangan);
setTotalHarga(menuKeranjang.total_harga);
};
const handleClose = () => {
setShowModal(false);
};
const tambah = () => {
setJumlah(jumlah + 1);
setTotalHarga(keranjangDetail.product.harga * (jumlah + 1));
};
const kurang = () => {
if (jumlah !== 1) {
setJumlah(jumlah - 1),
setTotalHarga(keranjangDetail.product.harga * (jumlah - 1));
}
};
const changeHandler = (event) => {
setKeterangan(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
handleClose();
const data = {
jumlah: jumlah,
total_harga: totalHarga,
product: keranjangDetail.product,
keterangan: keterangan,
};
axios
.put(API_URL + "keranjangs/" + keranjangDetail.id, data)
.then((res) => {
swal({
title: "Update Pesanan!",
text: "Sukses Update Pesanan " + data.product.nama,
icon: "success",
button: false,
timer: 1500,
});
})
.catch((error) => {
console.log("Error yaa ", error);
});
};
const hapusPesanan = (id) => {
handleClose();
axios
.delete(API_URL + "keranjangs/" + id)
.then((res) => {
swal({
title: "Hapus Pesanan!",
text: "Sukses Hapus Pesanan " + keranjangDetail.product.nama,
icon: "error",
button: false,
timer: 1500,
});
})
.catch((error) => {
console.log("Error yaa ", error);
});
};
const { keranjangs } = useState(props);
return (
<Col md={3} className="mt-3">
<h4>
<strong>Keranjang</strong>
</h4>
<hr />
{keranjangs.length !== 0 && (
<Card className="overflow-auto hasil ">
<ListGroup variant="flush">
<Row className="category-aktif">
<Col xs={2} className="ml-3 mt-2">
<h5 className="ml-2">Jml</h5>
</Col>
<Col>
<h5 className="mt-2">Produk</h5>
</Col>
<Col>
<strong className="float-right mr-3 mt-2">Total Harga</strong>
</Col>
</Row>
{keranjangs.map((menuKeranjang) => (
<ListGroup.Item
key={menuKeranjang.id}
onClick={() => handleShow(menuKeranjang)}
>
<Row>
<Col xs={2}>
<h4>
<Badge pill variant="primary">
{menuKeranjang.jumlah}
</Badge>
</h4>
</Col>
<Col>
<h5>{menuKeranjang.product.nama}</h5>
<p>Rp. {numberWithCommas(menuKeranjang.product.harga)}</p>
</Col>
<Col>
<strong className="float-right">
Rp. {numberWithCommas(menuKeranjang.total_harga)}
</strong>
</Col>
</Row>
</ListGroup.Item>
))}
<Keranjang
handleClose={handleClose}
{...this.state}
tambah={tambah}
kurang={kurang}
changeHandler={changeHandler}
handleSubmit={handleSubmit}
hapusPesanan={hapusPesanan}
/>
</ListGroup>
</Card>
)}
<TotalBayar keranjangs={keranjangs} {...this.props} />
</Col>
);
}
but it give error said ./src/components/Hasil.js Line 68:7: Expected an assignment or function call and instead saw an expression no-unused-expressions
But I don't know what to do, anyone can help me? thanks in advance
btw, here is my original class code before convert it into function https://pastebin.com/0vTJ81kJ
I think the actual issue is a few lines up from what is being blamed.
There's an extraneous comma after setJumlah(jumlah - 1)
const kurang = () => {
if (jumlah !== 1) {
setJumlah(jumlah - 1), // <-- trailing comma at end of line
setTotalHarga(keranjangDetail.product.harga * (jumlah - 1));
}
};
It should be
const kurang = () => {
if (jumlah !== 1) {
setJumlah(jumlah - 1);
setTotalHarga(keranjangDetail.product.harga * (jumlah - 1));
}
};
this.state line should be removed or replaced in a functional way:
<Keranjang
handleClose={handleClose}
**{...this.state}** This is not for functional components
tambah={tambah}
kurang={kurang}
changeHandler={changeHandler}
handleSubmit={handleSubmit}
hapusPesanan={hapusPesanan}
/>
And also is extrange to have a coma here
const kurang = () => {
if (jumlah !== 1) {
setJumlah(jumlah - 1),// why coma
setTotalHarga(keranjangDetail.product.harga * (jumlah - 1));
}
};
Related
When I click Place Order button in placeOrderScreen.js placeOrderHandler runs which dispatches createOrder. According to logic createOrder should be dispatched just once when I click Place Order button but here createOrder is being dispatched twice which I am compeletly unable to understand.
First createorder dispatches before useEffect(which is normal) and then it dispatches after useEffect.
Before useEffect runs
After useEffect runs
I just want to run it once when I click Place Order button.
placeOrderScreen.js
import React, { useEffect } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import {
Button,
Row,
Col,
ListGroup,
Image,
Card,
ListGroupItem,
} from 'react-bootstrap';
import { useDispatch, useSelector } from 'react-redux';
import Message from '../components/Message';
import CheckoutSteps from '../components/CheckoutSteps';
import {
createOrder,
ORDER_CREATE_RESET,
} from '../features/OrderFeature/orderCreateSlice';
import { USER_DETAILS_RESET } from '../features/UserFeature/userDetailsSlice';
const PlaceOrderScreen = () => {
const navigate = useNavigate();
const dispatch = useDispatch();
const cart = useSelector((store) => store.cart);
//Calculate Prices
const addDecimals = (num) => {
return (Math.round(num * 100) / 100).toFixed(2);
};
//Cart object ko modify karny k leye local copy bnai hy ...kun k kuch additional chezein add karni thien(prices)
const cartObject = { ...cart };
cartObject.itemsPrice = addDecimals(
cartObject.cartItems.reduce((acc, item) => acc + item.price * item.qty, 0)
);
cartObject.shippingPrice = addDecimals(cartObject.itemsPrice < 100 ? 0 : 100);
cartObject.taxPrice = addDecimals(
Number((0.15 * cartObject.itemsPrice).toFixed(2))
);
cartObject.totalPrice = (
Number(cartObject.itemsPrice) +
Number(cartObject.shippingPrice) +
Number(cartObject.taxPrice)
).toFixed(2);
const orderCreate = useSelector((store) => store.orderCreate);
const { order, success, error } = orderCreate;
useEffect(() => {
// agr sab kuch theek sy chal gya hy (orderSlice mein) aur data mil gya hy to...
if (success) {
// agr order data mila hy to usmein sy _id property nikalo
navigate(`/order/${order._id}`);
dispatch(ORDER_CREATE_RESET());
dispatch(USER_DETAILS_RESET());
}
// To remove order._id dependency warning
// eslint-disable-next-line
}, [navigate, success]);
const placeOrderHandler = () => {
dispatch(
createOrder({
orderItems: cart.cartItems,
shippingAddress: cart.shippingAddress,
paymentMethod: cart.paymentMethod,
itemsPrice: cartObject.itemsPrice, //taken from new object which was copy of cart object
shippingPrice: cartObject.shippingPrice,
taxPrice: cartObject.taxPrice,
totalPrice: cartObject.totalPrice,
})
);
};
return (
<>
<CheckoutSteps step1 step2 step3 step4 />
<Row>
<Col md={8}>
<ListGroup variant='flush'>
<ListGroup.Item>
<h2>Shipping</h2>
<p>
<strong>Address:</strong>
{cart.shippingAddress.address},{cart.shippingAddress.city},
{cart.shippingAddress.postalCode},{cart.shippingAddress.country}
,
</p>
</ListGroup.Item>
<ListGroup.Item>
<h2>Payment Method</h2>
<strong>Method:</strong>
{cart.paymentMethod}
</ListGroup.Item>
<ListGroup.Item>
<h2>Order Items</h2>
{cart.cartItems.length === 0 ? (
<Message>Your Cart is empty</Message>
) : (
<ListGroup variant='flush'>
{cart.cartItems.map((item, index) => {
return (
<ListGroupItem key={index}>
<Row>
<Col md={1}>
<Image
src={item.image}
alt={item.name}
fluid
rounded
/>
</Col>
<Col>
<Link to={`/product/${item.product}`}>
{item.name}
</Link>
</Col>
<Col md={4}>
{item.qty} x ${item.price}=${item.qty * item.price}
</Col>
</Row>
</ListGroupItem>
);
})}
</ListGroup>
)}
</ListGroup.Item>
</ListGroup>
</Col>
<Col md={4}>
<Card>
<ListGroup variant='flush'>
<ListGroup.Item>
<h2>Order Summary</h2>
</ListGroup.Item>
<ListGroup.Item>
<Row>
<Col>Items</Col>
<Col>${cartObject.itemsPrice}</Col>
</Row>
</ListGroup.Item>
<ListGroup.Item>
<Row>
<Col>Shipping</Col>
<Col>${cartObject.shippingPrice}</Col>
</Row>
</ListGroup.Item>
<ListGroup.Item>
<Row>
<Col>Tax</Col>
<Col>${cartObject.taxPrice}</Col>
</Row>
</ListGroup.Item>
<ListGroup.Item>
<Row>
<Col>Total</Col>
<Col>${cartObject.totalPrice}</Col>
</Row>
</ListGroup.Item>
<ListGroupItem>
{error && <Message variant='danger'>{error}</Message>}
</ListGroupItem>
<ListGroup.Item>
<Button
type='button'
className='btn-block'
disabled={cart.cartItems === 0}
onClick={placeOrderHandler}
>
Place Order
</Button>
</ListGroup.Item>
</ListGroup>
</Card>
</Col>
</Row>
</>
);
};
export default PlaceOrderScreen;
orderCreateSlice.js
import { createSlice, createAsyncThunk } from '#reduxjs/toolkit';
import axios from 'axios';
const initialState = {};
export const createOrder = createAsyncThunk(
'createOrder',
async (order, thunkAPI) => {
try {
const {
//userLogin .getState() sy nikalo aur userInfo variable usy day do
userLogin: { userInfo },
} = thunkAPI.getState();
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.post(`/api/orders`, order, config);
return data;
} catch (error) {
const newError =
error.response && error.response.data.message
? error.response.data.message
: error.message;
//This will end up in rejected section as payload... just error return karny sy fulfilled action run hora tha
return thunkAPI.rejectWithValue(newError);
}
}
);
const orderCreateSlice = createSlice({
name: 'orderCreate',
initialState,
reducers: {
ORDER_CREATE_RESET: () => {
return {};
},
},
extraReducers: {
//extra reducers sirf async operations k leye hein ... normally reducer use hongay
[createOrder.pending]: (state) => {
return {
loading: true,
};
},
[createOrder.fulfilled]: (state, action) => {
return {
loading: false,
success: true,
order: action.payload,
};
},
[createOrder.rejected]: (state, action) => {
return {
loading: false,
error: action.payload,
};
},
},
});
export const { ORDER_CREATE_RESET } = orderCreateSlice.actions;
export default orderCreateSlice.reducer;
store.js
import { configureStore } from '#reduxjs/toolkit';
import productListReducer from './features/productListFeature/productListSlice';
import productDetailsReducer from './features/productListFeature/productDetailSlice';
import CartReducer from './features/addToCart/cartSlice';
import userLoginReducer from './features/UserFeature/loginUserSlice';
import userRegisterReducer from './features/UserFeature/registerUserSlice';
import userDetailsReducer from './features/UserFeature/userDetailsSlice';
import userUpdateProfileReducer from './features/UserFeature/updateProfileSlice';
import orderCreateReducer from './features/OrderFeature/orderCreateSlice';
import orderDetailsReducer from './features/OrderFeature/orderDetailsSlice';
// yahan hum local storage sy data ly rahy hein jo cartSlice mein store kea tha ... JSON.parse is leye run kea hy kun k stringify kea tha data cartSlice mein
const cartItemsFromStorage = localStorage.getItem('cartItems')
? JSON.parse(localStorage.getItem('cartItems'))
: [];
const userInfoFromStorage = localStorage.getItem('userInfo')
? JSON.parse(localStorage.getItem('userInfo'))
: null; //agr user info ni available to null return kar do
const shippingAddressFromStorage = localStorage.getItem('shippingAddress')
? JSON.parse(localStorage.getItem('shippingAddress'))
: {};
const initialState = {
cart: {
cartItems: cartItemsFromStorage,
shippingAddress: shippingAddressFromStorage,
},
userLogin: {
userInfo: userInfoFromStorage,
},
};
const store = configureStore({
reducer: {
productList: productListReducer,
productDetails: productDetailsReducer,
cart: CartReducer,
userLogin: userLoginReducer,
userRegister: userRegisterReducer,
userDetails: userDetailsReducer,
userUpdateProfile: userUpdateProfileReducer,
orderCreate: orderCreateReducer,
orderDetails: orderDetailsReducer,
},
preloadedState: initialState, //for local storage
});
export default store;
I am getting error Parsing error: Unexpected token, expected "," at line 55 while dispatching addToCart action with two parameters. I am using redux toolkit. At line 27 this dispatch method is working properly. Please see the picture below. I am passing two parameters as an object.(redux toolkit syntax for passing parameters in async function)
Error at line 55
//CartScreen
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Link, useParams, useLocation } from 'react-router-dom';
import {
Row,
Col,
ListGroup,
Image,
Form,
Button,
Card,
} from 'react-bootstrap';
import Message from '../components/Message';
import { addToCart } from '../features/addToCart/cartSlice';
const CartScreen = () => {
const { id } = useParams();
const location = useLocation();
const qty = location.search ? Number(location.search.split('=')[1]) : 1;
const dispatch = useDispatch();
const cart = useSelector((store) => store.cart);
const { cartItems } = cart;
console.log(cart);
useEffect(() => {
if (id) {
dispatch(addToCart({ id, qty }));
}
}, [dispatch, id, qty]);
return (
<Row>
<Col md={8}>
<h1>Shopping Cart</h1>
{cartItems.length === 0 ? (
<Message>
Your Cart is empty <Link to='/'>Go Back</Link>{' '}
</Message>
) : (
<ListGroup variant='flush'>
{cartItems.map((item) => {
<ListGroup.Item key={item.product}>
<Row>
<Col md={2}>
<Image src={item.image} alt={item.name} fluid rounded />
</Col>
<Col md={3}>
<Link to={`/product/${item.product}`}>{item.name} </Link>
</Col>
<Col md={2}>${item.price}</Col>
<Col md={2}>
<Form.Control
as='select'
value={qty}
onChange={(e) => dispatch(addToCart({item.product,e.target.value}))}
>
{
[...Array(item.countInStock).keys()].map((x) => (
<option key={x + 1} value={x + 1}>
{x + 1}
</option>
))
}
console.log(...Array(product.countInStock).keys())
</Form.Control>
</Col>
</Row>
</ListGroup.Item>;
})}
</ListGroup>
)}
</Col>
<Col md={2}></Col>
<Col md={2}></Col>
</Row>
);
};
export default CartScreen;
//CartSlice
import { createSlice, createAsyncThunk, current } from '#reduxjs/toolkit';
import axios from 'axios';
export const addToCart = createAsyncThunk(
'addToCart',
async ({ id, qty }, thunkAPI) => {
//getting id and qty from cartScreen
try {
const { data } = await axios(`/api/products/${id}`);
localStorage.setItem(
'cartItems',
JSON.stringify(thunkAPI.getState().cart.cartItems)
); //data ko local storage save rakhny k lye... isko humny json.stringify kea hy kun k local storage mein sirf string store kr sakty... yahan hum ny local storage mein store kea hy lekin isko fetch store mein jakar krein gay
const productData = {
product: data._id,
name: data.name,
image: data.image,
price: data.price,
countInStock: data.countInStock,
qty,
};
return productData;
} catch (error) {
console.log(error);
}
}
);
const initialState = {
cartItems: [],
};
const cartSlice = createSlice({
name: 'cartReducer',
initialState,
extraReducers: {
[addToCart.pending]: (state) => {
state.cartItems = [];
},
[addToCart.fulfilled]: (state, action) => {
const item = action.payload;
const existItem = state.cartItems.find(
(cartItem) => cartItem.product === item.product
);
if (existItem) {
return {
...state,
cartItems: state.cartItems.map((cartItem) => {
return cartItem.product === existItem.product ? item : cartItem;
}),
};
} else {
state.cartItems = [...state.cartItems, item];
}
},
[addToCart.rejected]: (state) => {
state.cartItems = 'Some error has occured';
},
},
});
export default cartSlice.reducer;
I'm trying to get the updated/newly created records and send it to the backend in "queryparam"
import React, { useState, useEffect } from "react";
//import { Container, Row, Col } from "reactstrap";
// import Box from "#mui/material/Box";
// import "bootstrap/dist/css/bootstrap.css";
// import "./index.css";
const Index = () => {
const [formValues, setFormValues] = useState([
{ orderno: 0, inputValue1: "", inputValue2: "", checked: false }
]);
const [isDisabled, setDisabled] = useState(false);
// const [inputVal1, setInputval1] = useState();
const [isChanged, setIsChanged] = useState([]);
const [error, setError] = useState(false);
const [orderNumber, setOrderNumber] = useState(1);
const addFormFields = () => {
// if (error) {
// setDisabled(false)
// }
// else {
// setDisabled(true)
// }
setFormValues((prevState) => [
...prevState,
{
orderno: orderNumber,
inputValue1: "",
inputValue2: "",
checked: false
}
]);
setOrderNumber((prev) => prev + 1);
};
const removeFormFields = (i) => {
let newFormValues = [...formValues];
newFormValues.splice(i, 1);
setFormValues(newFormValues);
setOrderNumber((prev) => prev - 1);
};
const onChangeFieldValue = (index, key, value) => {
setFormValues((prevState) => {
let copyState = [...prevState];
if (value?.length > 0) {
setError(false);
} else {
setError(true);
}
copyState[index][key] = value;
return copyState;
});
};
const saveFields = (e) => {
const queryparam = {
inputData: formValues
};
setIsChanged(queryparam);
setIsChanged((prevState, nextState) => {
let copyState = [];
if (prevState === nextState) {
copyState = [...prevState];
} else {
copyState = [...nextState];
}
return copyState;
});
console.log(isChanged, "lllllllll");
};
// useEffect(() => {
// saveFields()
// }, [isChanged])
return (
<>
{formValues.map((element, index) => (
<div className="form-inline" key={index}>
{/* <Container>
<Row>
<Col xs="12" sm="6"> */}
<label>{index + 1}</label>
<input
type="text"
value={element.inputVal1}
onChange={(e) =>
onChangeFieldValue(index, "inputValue1", e.target.value)
}
/>
<input
type="text"
value={element.inputVal2}
required
onChange={(e) =>
onChangeFieldValue(index, "inputValue2", e.target.value)
}
/>
{/* </Col>
<Col xs="12" sm="6">
<Box> */}
<button
className={`button ${error ? "add" : "btn-secondary"}`}
type="button"
disabled={error}
onClick={(e) => addFormFields(e)}
>
Add{console.log(isDisabled, "ooooooo", error)}
</button>
<button
type="button"
className="button remove"
onClick={() => removeFormFields(index)}
>
Remove
</button>
{/* </Box>
</Col>
</Row>
</Container> */}
</div>
))}
{/* <Row>
<Col sm="6" md={{ size: 4, offset: 2 }}>
<Box> */}
<button
type="button"
className="button save"
onClick={(e) => saveFields(e)}
>
Save
</button>
<button
type="button"
className="button remove"
//onClick={(e) => cancelFields(e)}
>
cancel
</button>
{/* </Box>
</Col>
</Row> */}
</>
);
};
export default Index;
https://codesandbox.io/s/black-fire-ixeir?file=/src/App.js:3662-3701
In the above link,
Step1 : when I add values for inputs "123" in input1 and "345" in input2.Then when I click on "Save" the values sent are {"input1":"123","input2":"345"}.
Step2: Again I try to add one row for inputs "456" in input1 and "678" in input2.Then when I click on save the values sent are {"input1":"456","input2":"678"}.
When I edit the existing row, for example the first row values and when I click on "Save" then only the first row value should be sent as the second row values hasn't changed.Also, If I add new rows then the newly added only should be sent if the existing row values aren't changed. Is there any way to send only the updated/newly created values to the backend using react hook
You could use a separate changes object to track changes by orderno property; saved during add/update/remove, and committed when submitting.
const [changes, setChanges] = useState({});
...
const addFormFields = () => {
const newItem = {
orderno: orderNumber,
inputValue1: "",
inputValue2: "",
checked: false,
type: "add"
};
setFormValues((values) => [...values, newItem]);
setChanges((changes) => ({
...changes,
[newItem.orderno]: newItem
}));
setOrderNumber((prev) => prev + 1);
};
const removeFormFields = (index) => {
const item = {
...formValues[index],
type: "remove"
};
setFormValues((values) => values.filter((el, i) => i !== index));
setChanges((changes) => ({
...changes,
[item.orderno]: item
}));
};
const onChangeFieldValue = (index, key, value) => {
const item = {
...formValues[index],
[key]: value,
type: "edit"
};
setFormValues((prevState) => {
if (value?.length > 0) {
setError(false);
const copyState = [...prevState];
copyState[index] = item;
return copyState;
} else {
setError(true);
return prevState;
}
});
setChanges((changes) => ({
...changes,
[item.orderno]: item
}));
};
const saveFields = (e) => {
const queryparam = {
inputData: Object.values(changes)
};
console.log("Changes to commit", queryparam);
setChanges({});
};
I have created a stepper as a functional component as below
import NewProfile from './NewProfile';
function getSteps() {
return ['Carete Profile', 'Contact'];
}
function getStepContent(step) {
switch (step) {
case 0:
return <NewProfile type={valueTobePass}></NewProfile>;
default:
return <contact></contact>;
}
}
export default function HorizontalLinearStepper(props,previousState)
{
const classes = useStyles();
const [activeStep, setActiveStep] = React.useState(0);
const [publisherId, setPublisherId] = React.useState(0);
const [skipped, setSkipped] = React.useState(new Set());
const steps = getSteps();
const isStepOptional = (step) => {
return (step === 1 ||
step === 2)
};
console.log(props.newUserId);
const isStepSkipped = (step) => {
return skipped.has(step);
};
const addPublisherid =(publisherId) => {
setPublisherId(publisherId);
console.log(publisherId)
}
const handleNext = () => {
let newSkipped = skipped;
if (isStepSkipped(activeStep)) {
newSkipped = new Set(newSkipped.values());
newSkipped.delete(activeStep);
}
setActiveStep((prevActiveStep) => prevActiveStep + 1);
setSkipped(newSkipped);
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
setActiveStep((prevActiveStep) => prevActiveStep + 1);
setSkipped((prevSkipped) => {
const newSkipped = new Set(prevSkipped.values());
newSkipped.add(activeStep);
return newSkipped;
});
}
return (
<div className={classes.root}>
<Stepper activeStep={activeStep}>
{steps.map((label, index) => {
const stepProps = {};
const labelProps = {};
if (isStepOptional(index)) {
labelProps.optional = <Typography variant="caption">Optional</Typography>;
}
if (isStepSkipped(index)) {
stepProps.completed = false;
}
return (
<Step key={index} {...stepProps}>
<StepLabel {...labelProps}>{label}</StepLabel>
</Step>
);
})}
{props.step}
</Stepper>
<div>
{activeStep === steps.length ? (
<div>
<Typography className={classes.instructions}>
All steps completed - you're finished
</Typography>
</div>
) : (
<div>
<Typography className={classes.instructions}>{getStepContent(activeStep,previousState,props.type)}</Typography>
<div>
<Button disabled={activeStep === 0} onClick={handleBack} className={classes.button}>
Back
</Button>
{isStepOptional(activeStep) && (
<Button
variant="contained"
color="primary"
onClick={handleSkip}
className={classes.button}
>
Skip
</Button>
)}
<Button
variant="contained"
color="primary"
onClick={handleNext}
className={classes.button}
>
{activeStep === steps.length - 1 ? 'Finish' : 'Next'}
</Button>
</div>
</div>
)}
</div>
</div>
);
}
and the step is class component
class NewProfile extends Component {
constructor(props) {
super(props);
this.state = {
Name: '',
newUserId:'',
}
}
editAccountDetails = () => {
axios.post(`url`, {
"Name": this.state.Name,
})
.then(response => response.data)
.then((data) => {
this.setState({newUserId:data.id})
}).catch(error => { console.log(error); })
}
render() {
return <div>
<TextField }}
onChange={(event) => {
this.setState({ "Name":
event.target.value })
}} />
<Button onClick={this.editAccountDetails} >
Submit </MButton>
</div>
</div>
}
}
const NewProfileHOC = withStyles(styles)(NewProfile);
export default connect(mapStateToProps, mapDispatchToProps)(NewProfileHOC);
I want to retrieve the 'state' of the 'NewProfile' Component(Class Component) in the Stepper Component (Functional Component) for my further process
i tried with callBack function and context it is not working please help me out with this
thank you in advance
I've two different prices,
when i check the checkbox for second price,
the state show and display the second price properly
but when i press the pay button of that product with second price, it will send the first price
instead of what I've checked which was second price.
so i want increment both prices separately when i checked the check box and
it sends the specific price to the payment process
import React, { useState, useEffect } from "react";
import {
getProducts,
getBraintreeClientToken,
processPayment,
createOrder
} from "./apiCore";
import { emptyCart } from "./cartHelpers";
import { isAuthenticated } from "../auth";
import { Link } from "react-router-dom";
import "braintree-web";
import DropIn from "braintree-web-drop-in-react";
import { makeStyles } from '#material-ui/core/styles';
import TextField from '#material-ui/core/TextField';
const useStyles = makeStyles((theme) => ({
root: {
'& > *': {
margin: theme.spacing(1),
width: '25ch',
},
},
}));
const Checkout = ({ products, setRun = f => f, run = undefined }) => {
const classes = useStyles();
const [data, setData] = useState({
loading: false,
success: false,
clientToken: null,
error: "",
instance: {},
address: "",
mobile:""
});
>>>>>> const [price, setPrice]= useState(() => () => getTotal())
>>>>>> const [isChecked, setIsChecked]= useState(false);
const userId = isAuthenticated() && isAuthenticated().user._id;
const token = isAuthenticated() && isAuthenticated().token;
const getToken = (userId, token) => {
getBraintreeClientToken(userId, token).then(data => {
if (data.error) {
setData({ ...data, error: data.error });
} else {
setData({ clientToken: data.clientToken });
}
});
};
useEffect(() => {
getToken(userId, token);
}, []);
const handleAddress = event => {
setData({ ...data, address: event.target.value });
};
const handleMobile = event => {
setData({ ...data, mobile: event.target.value });
};
>>>>>> const getTotal = () => {
>>>>>> return products.reduce((currentValue, nextValue) => {
>>>>>> return currentValue + nextValue.count * nextValue.price;
>>>>>>
>>>>>> }, 0);
>>>>>> };
>>>>>> const getTotal2 = () => {
>>>>>> return products.reduce((currentValue, nextValue) => {
>>>>>> return currentValue + nextValue.count * nextValue.price2;
>>>>>> }, 0);
>>>>>> };**
const showCheckout = () => {
return isAuthenticated() ? (
<div>{showDropIn()}</div>
) : (
<Link to="/signin">
<button className="btn btn-primary">Sign in to checkout</button>
</Link>
);
};
let deliveryAddress = data.address
let deliveryMobile = data.mobile
const buy = () => {
setData({ loading: true });
// send the nonce to your server
// nonce = data.instance.requestPaymentMethod()
let nonce;
let getNonce = data.instance
.requestPaymentMethod()
.then(data => {
// console.log(data);
nonce = data.nonce;
// once you have nonce (card type, card number) send nonce as 'paymentMethodNonce'
// and also total to be charged
// console.log(
// "send nonce and total to process: ",
// nonce,
// getTotal(products)
// );
>>>>>> **const paymentData = {
>>>>>> paymentMethodNonce: nonce,
>>>>>> amount: getTotal(products)
>>>>>> };**
processPayment(userId, token, paymentData)
.then(response => {
console.log(response);
// empty cart
// create order
const createOrderData = {
products: products,
transaction_id: response.transaction.id,
amount: response.transaction.amount,
address: deliveryAddress,
mobile: deliveryMobile
};
createOrder(userId, token, createOrderData)
.then(response => {
emptyCart(() => {
setRun(!run); // run useEffect in parent Cart
console.log(
"payment success and empty cart"
);
setData({
loading: false,
success: true
});
});
})
.catch(error => {
console.log(error);
setData({ loading: false });
});
})
.catch(error => {
console.log(error);
setData({ loading: false });
});
})
.catch(error => {
// console.log("dropin error: ", error);
setData({ ...data, error: error.message });
});
};
const showDropIn = () => (
<div onBlur={() => setData({ ...data, error: "" })}>
{data.clientToken !== null && products.length > 0 ? (
<div>
<div className="gorm-group mb-3">
<label className="text-muted">Delivery address:</label>
<textarea
onChange={handleAddress}
className="form-control"
value={data.address}
placeholder="Type your delivery address here..."
/>
</div>
<div className="gorm-group mb-3">
<label className="text-muted">mobile number:</label>
<form className={classes.root} noValidate autoComplete="off">
<TextField placeholder="mobile number" onChange={handleMobile} type="text" value={data.mobile} id="outlined-basic" label="mobile" variant="outlined" />
</form>
</div>
<DropIn
options={{
authorization: data.clientToken,
paypal: {
flow: "vault"
}
}}
onInstance={instance => (data.instance = instance)}
/>
<button onClick={buy} className="btn btn-success btn-block">
Pay
</button>
</div>
) : null}
</div>
);
const showError = error => (
<div
className="alert alert-danger"
style={{ display: error ? "" : "none" }}
>
{error}
</div>
);
const showSuccess = success => (
<div
className="alert alert-info"
style={{ display: success ? "" : "none" }}
>
Thanks! Your payment was successful!
</div>
);
const showLoading = loading =>
loading && <h2 className="text-danger">Loading...</h2>;
return (
<div>
>>>>>> **<form>
>>>>>> <h1>قیمت کل: {isChecked ? getTotal2() : getTotal()} </h1>
>>>>>> <label>نیم لیتر :</label>
>>>>> <input type="checkbox"
>>>>>> checked={isChecked}
>>>>>> onChange={(e)=>{setIsChecked(e.target.checked)}}/>
>>>>>> </form>**
{showLoading(data.loading)}
{showSuccess(data.success)}
{showError(data.error)}
{showCheckout()}
</div>
);
};
export default Checkout;
my card component
import React, { useState, version,useEffect } from 'react';
import { Link, Redirect } from 'react-router-dom';
import ShowImage from './ShowImage';
import moment from 'moment';
import { addItem, updateItem, removeItem } from './cartHelpers';
import logo from '../images/logo.svg'
//material ui
import Card from '#material-ui/core/Card';
import CardContent from '#material-ui/core/CardContent';
import { makeStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import Grid from '#material-ui/core/Grid'
import { Typography } from '#material-ui/core';
import CardHeader from '#material-ui/core/CardHeader';
import CardMedia from '#material-ui/core/CardMedia';
import CardActions from '#material-ui/core/CardActions';
import Collapse from '#material-ui/core/Collapse';
import Avatar from '#material-ui/core/Avatar';
import IconButton from '#material-ui/core/IconButton';
import MoreVertIcon from '#material-ui/icons/MoreVert';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Menu from '#material-ui/core/Menu';
import MenuItem from '#material-ui/core/MenuItem';
import { create } from 'jss';
import rtl from 'jss-rtl';
import { StylesProvider, jssPreset } from '#material-ui/core/styles';
const jss = create({ plugins: [...jssPreset().plugins, rtl()] });
const useStyles = makeStyles((theme) => ({
stock: {
marginBottom: '1rem'
},
Button: {
...theme.typography.button,
padding: '.3rem',
minWidth: 10,
},
media: {
height: 0,
paddingTop: '56.25%', // 16:9
},
title: {
backgroundColor: '#D8D8D8'
},
grid: {
padding: '0'
},
cardFont:{
...theme.typography.body,
textAlign:'right',
marginTop:'.8rem',
marginRight:'1rem'
},productName:{
...theme.typography.body,
textAlign:'right',
},
cardButton:{
marginLeft:'1.4rem'
}
}));
const Cardd = ({
product,
showViewProductButton = true,
showAddToCartButton = true,
cartUpdate = false,
showRemoveProductButton = false,
setRun = f => f,
run = undefined
// changeCartSize
}) => {
const [redirect, setRedirect] = useState(false);
const [count, setCount] = useState(product.count);
//material ui
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
// console.log(price)
const classes = useStyles()
const showViewButton = showViewProductButton => {
return (
showViewProductButton && (
<Link to={`/product/${product._id}`} className="mr-2">
<Button className={classes.Button} size="small" variant="contained">مشاهده محصول</Button>
</Link>
)
);
};
const addToCart = () => {
// console.log('added');
addItem(product, setRedirect(true));
};
const shouldRedirect = redirect => {
if (redirect) {
return <Redirect to="/cart" />;
}
};
const showAddToCartBtn = showAddToCartButton => {
return (
showAddToCartButton && (
<Button className={classes.Button} size="small" onClick={addToCart} variant="contained" color="primary" disableElevation>
اضافه کردن به سبد
</Button>
)
);
};
const showStock = quantity => {
return quantity > 0 ? (
<Button disabled size="small" className={classes.stock}>موجود </Button>
) : (
<Button className={classes.stock}>ناموجود </Button>
);
};
const handleChange = productId => event => {
setRun(!run); // run useEffect in parent Cart
setCount(event.target.value < 1 ? 1 : event.target.value);
if (event.target.value >= 1) {
updateItem(productId, event.target.value);
}
};
const showCartUpdateOptions = cartUpdate => {
return (
cartUpdate && (
<div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className="input-group-text">تعداد</span>
</div>
<input type="number" className="form-control" value={count} onChange={handleChange(product._id)} />
</div>
</div>
)
);
};
const showRemoveButton = showRemoveProductButton => {
return (
showRemoveProductButton && (
<Button className={classes.Button} size="small" variant="contained" color="secondary" disableElevation
onClick={() => {
removeItem(product._id);
setRun(!run); // run useEffect in parent Cart
}}
>
حذف محصول
</Button>
)
);
};
return (
<Grid container direction='column' >
<Grid item >
<Card style={{margin:'1rem'}}>
<Grid item className={classes.title}>
<Typography className={classes.productName} variant='h6'>
{product.name}
</Typography>
</Grid>
<CardHeader
avatar={
<Avatar alt="Remy Sharp" src={logo} className={classes.green}>
</Avatar>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title="روغنک"
subheader="September 14, 2016"
/>
<CardContent className={classes.grid} >
{shouldRedirect(redirect)}
<ShowImage item={product} url="product" />
<StylesProvider jss={jss}>
<Typography className={classes.cardFont} variant="body2" component="p">
{product.description.substring(0, 100)}
</Typography>
</StylesProvider>
<div>
<Button aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>
Open Menu
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</div>
<Typography className={classes.cardFont} variant="body2" component="p">
$یک لیتر {product.price}
</Typography>
<Typography className={classes.cardFont} variant="body2" component="p">
$نیم لیتر {product.price2}
</Typography>
<Typography className={classes.cardFont} variant="body2" component="p">
Category: {product.category && product.category.name}
</Typography>
<Typography className={classes.cardFont} variant="body2" component="p">
Added on {moment(product.createdAt).fromNow()}
</Typography>
<Typography className={classes.cardFont} variant="body2" component="p">
{showStock(product.quantity)}
</Typography>
<br />
<Grid container >
<Grid item className={classes.cardButton} >
{showViewButton(showViewProductButton)}
</Grid>
<Grid item className={classes.cardButton}>
{showAddToCartBtn(showAddToCartButton)}
</Grid>
<Grid item className={classes.cardButton}>
{showRemoveButton(showRemoveProductButton)}
</Grid>
</Grid>
{showCartUpdateOptions(cartUpdate)}
</CardContent>
</Card>
</Grid>
</Grid>
// <div className="card ">
// <div className="card-header card-header-1 ">{product.name}</div>
// <div className="card-body">
// {shouldRedirect(redirect)}
// <ShowImage item={product} url="product" />
// <p className="card-p mt-2">{product.description.substring(0, 100)} </p>
// <p className="card-p black-10">$ {product.price}</p>
// <p className="black-9">Category: {product.category && product.category.name}</p>
// <p className="black-8">Added on {moment(product.createdAt).fromNow()}</p>
// {showStock(product.quantity)}
// <br />
// {showViewButton(showViewProductButton)}
// {showAddToCartBtn(showAddToCartButton)}
// {showRemoveButton(showRemoveProductButton)}
// {showCartUpdateOptions(cartUpdate)}
// </div>
// </div>
);
};
export default Cardd;
CartHelper component
export const addItem = (item = [], count = 0, next = f => f) => {
let cart = [];
if (typeof window !== 'undefined') {
if (localStorage.getItem('cart')) {
cart = JSON.parse(localStorage.getItem('cart'));
}
cart.push({
...item,
count: 1
});
// remove duplicates
// build an Array from new Set and turn it back into array using Array.from
// so that later we can re-map it
// new set will only allow unique values in it
// so pass the ids of each object/product
// If the loop tries to add the same value again, it'll get ignored
// ...with the array of ids we got on when first map() was used
// run map() on it again and return the actual product from the cart
cart = Array.from(new Set(cart.map(p => p._id))).map(id => {
return cart.find(p => p._id === id);
});
localStorage.setItem('cart', JSON.stringify(cart));
next();
}
};
export const itemTotal = () => {
if (typeof window !== 'undefined') {
if (localStorage.getItem('cart')) {
return JSON.parse(localStorage.getItem('cart')).length;
}
}
return 0;
};
export const getCart = () => {
if (typeof window !== 'undefined') {
if (localStorage.getItem('cart')) {
return JSON.parse(localStorage.getItem('cart'));
}
}
return [];
};
export const updateItem = (productId, count) => {
let cart = [];
if (typeof window !== 'undefined') {
if (localStorage.getItem('cart')) {
cart = JSON.parse(localStorage.getItem('cart'));
}
cart.map((product, i) => {
if (product._id === productId) {
cart[i].count = count;
}
});
localStorage.setItem('cart', JSON.stringify(cart));
}
};
export const removeItem = productId => {
let cart = [];
if (typeof window !== 'undefined') {
if (localStorage.getItem('cart')) {
cart = JSON.parse(localStorage.getItem('cart'));
}
cart.map((product, i) => {
if (product._id === productId) {
cart.splice(i, 1);
}
});
localStorage.setItem('cart', JSON.stringify(cart));
}
return cart;
};
export const emptyCart = next => {
if (typeof window !== 'undefined') {
localStorage.removeItem('cart');
next();
}
};