import React, { useState, Component } from 'react';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Row, Col, CardHeader, CardBody, Card, } from 'reactstrap';
const ModalBuySell = (props) => {
const {
buttonLabel,
className
} = props;
const datas = props;
const [modal, setModal] = useState(false);
const toggle = () => setModal(!modal);
return (
<div>
<Button color="danger" onClick={toggle}>Buy / Sell</Button>
<Modal isOpen={modal} toggle={toggle} className={className}>
<ModalHeader toggle={toggle}>{datas.name} (No. ID {datas.id}) Transaction(s)</ModalHeader>
<ModalBody>
<Row>
<Col>
<b>In-hand Quantity</b>
</Col>
<Col xs="1">
<i className="fa fa-arrow-right"></i>
</Col>
<Col>
{datas.inHand}
</Col>
</Row>
</ModalBody>
<ModalFooter>
<Button color="secondary" onClick={toggle}>Cancel</Button>
</ModalFooter>
</Modal>
</div>
);
}
export default ModalBuySell;
I tried to give my button some onChange function but first i need to make this to class, i'm beginner so i just search on the internet but all the solutions makes me use class instead of my code like that.
Related
I have encouneterd a problem that cannot find a solution in react-redux! I have a function that lives on Child component: "onClick={() => addToCart(product)}" Everytime I click on the button on UI of the application an error pops up saying: "TypeError: addToCart is not a function". I have tried several workarounds but in vain:
Parent component code:
class Jeans extends Component {
render () {
return (
<>
<PanelHeader size="sm" />
<ProductList
addToCart = {this.addToCart}
products={jeans}
image={jeans1}
header='Jeans For Men'
description='Foundation Of Contemporary Wardrobes,
Whether Tailored Or Super Skinny, Straight or Slim,
Biker or Destroyed, Our Denim Collection Caters To
Every Style And Silhouette.'
/>
</>
);
}
}
const mapStateToProps = (state)=> {
return {
products: state.products
}
}
const mapDispatchToProps = (dispatch) => {
return {
addToCart: (id) => {dispatch(addToCart(id))}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Jeans);```
and Child component where the function lives:
```class ProductCard extends Component {
render() {
const {image, product, key, addToCart} = this.props
return (
<Col
lg={4}
md={6}
sm={6}
xs={12}
className="font-icon-list"
key={key}
><Card>
<CardImg img src={image} alt="product"/>
<CardBody>
<CardTitle className='d-inline align-middle text-danger'>{product.title}</CardTitle>
<CardTitle className='d-inline align-middle float-right h5'><strong>{product.price}</strong></CardTitle>
<CardText className='my-2'>{product.description}</CardText>
<Button>
<div className="col-md-12 text-center">
<div className="buttons d-flex flex-row">
<div className="cart"><i className="fa fa-shopping-cart"></i>
</div>
<button onClick={() => addToCart(product)} className="btn btn-success cart-button px-5">Add to Cart</button>
</div>
</div>
</Button>
</CardBody>
</Card>
</Col>
)
}
}
export default ProductCard```
**Thank you in advance for your time reviewing my question!**
There is an intermediate component between Parent (Jeans) and Child (Productcard) called (Productlist) so the order goes: "Jeans" --> "ProductList" --> "ProductCard".
ProductList component:
const ProductList = ({products, header, description, image, addToCart}) => {
return (
<div className="content">
<Row>
<Col md={12}>
<Card>
<CardHeader>
<h5 className="title">{header}</h5>
<p className="category">{description}</p>
</CardHeader>
<CardBody className="all-icons">
<Row>
{products.map((product, key) => {
return (
<ProductCard
addToCart = {addToCart}
key={key}
product={product}
image={image}
/>
);
})}
</Row>
</CardBody>
</Card>
</Col>
</Row>
</div>
);
}
export default ProductList;```
index.js consists of the following code:
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route, Switch, Redirect } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.css";
import "assets/scss/now-ui-dashboard.scss?v1.5.0";
import "assets/css/demo.css";
import { Provider } from "react-redux";
import AdminLayout from "layouts/Admin.js";
import store from "./redux/store"
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<Switch>
<Route path="/admin" render={(props) => <AdminLayout {...props} />} />
<Redirect to="/admin/dashboard" />
</Switch>
</BrowserRouter>
</Provider>,
document.getElementById("root")
);
I'd like to create an order summary component on the right hand side as shown below: How the UI looks
However, I'm not sure how to go about this as I am quite new to MERN stack. This is the component for the how the restaurant details are displayed:
import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Grid, CircularProgress } from "#material-ui/core";
import useStyles from "./styles";
import { useParams } from "react-router-dom";
import { restaurantDetails } from "../../actions/restaurants";
import { TextField, Button, Typography, Paper } from "#material-ui/core";
import { LinearProgress } from "#material-ui/core";
import { Container, Row, Col } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.css";
import OrderSummary from "./OrderSummary/OrderSummary";
const RestaurantDetails = (props) => {
const classes = useStyles();
const dispatch = useDispatch();
let { _id } = useParams();
const [restaurantInfo, setRestaurantInfo] = useState();
useEffect(() => {
try {
dispatch(restaurantDetails(_id)).then((res) => setRestaurantInfo(res));
console.log("this is restaurantInfo" + restaurantInfo);
console.log(_id);
} catch (e) {
console.error(e);
}
}, [dispatch]);
return !restaurantInfo ? (
<CircularProgress />
) : (
<Container>
<LinearProgress variant="determinate" value="20" color="secondary" />;
<Row>
<Col sm={8}>
{" "}
<div className={classes.root}>
<Grid container spacing={3}>
<Grid item xs={12}>
<Paper className={classes.paper}>{restaurantInfo.name} </Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}>{restaurantInfo.categoryname1}</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}>{restaurantInfo.categoryname2}</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<div className="">
<img alt="" className="" src="images/3981417.jpg" />
<div className="">
<div className="">
<h3 className="">{restaurantInfo.itemName11}</h3>
<p className="">description here</p>
<h6 className="">£{restaurantInfo.itemPrice11}</h6>
<Button variant="contained" color="secondary">
Add To Order
</Button>
</div>
</div>
</div>
</Grid>
<Grid item xs={6} sm={3}>
<div className="">
<img alt="" className="" src="images/3981417.jpg" />
<div className="">
<div className="">
<h3 className="">{restaurantInfo.itemName12}</h3>
<p className="">description here</p>
<h6 className="">£{restaurantInfo.itemPrice12}</h6>
<Button variant="contained" color="secondary">
Add To Order
</Button>
</div>
</div>
</div>
</Grid>
<Grid item xs={6} sm={3}>
<div className="">
<img alt="" className="" src="images/3981417.jpg" />
<div className="">
<div className="">
<h3 className="">{restaurantInfo.itemName21}</h3>
<p className="">description here</p>
<h6 className="">£{restaurantInfo.itemPrice21}</h6>
<Button variant="contained" color="secondary">
Add To Order
</Button>
</div>
</div>
</div>
</Grid>
<Grid item xs={6} sm={3}>
<div className="">
<img alt="" className="" src="images/3981417.jpg" />
<div className="">
<div className="">
<h3 className="">{restaurantInfo.itemName22}</h3>
<p className="">description here</p>
<h6 className="">£{restaurantInfo.itemPrice22}</h6>
<Button variant="contained" color="secondary">
Add To Order
</Button>
</div>
</div>
</div>
</Grid>
</Grid>
</div>
</Col>
<OrderSummary />
</Row>
</Container>
// <div>
// <h2>Restaurant id is: {_id}</h2>
// <h2>Restaurant name is: {restaurantInfo.name}</h2>
// </div>
);
};
export default RestaurantDetails;
This is the Order Summary component at the moment. Obviously, I would like to display the item names and prices when they are added in order to checkout
import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Grid, CircularProgress } from "#material-ui/core";
import useStyles from "./styles";
import { Row, Col } from "react-bootstrap";
import { TextField, Button, Typography, Paper } from "#material-ui/core";
import Card from "#material-ui/core/Card";
import CardContent from "#material-ui/core/CardContent";
import CardHeader from "#material-ui/core/CardHeader";
import CardActions from "#material-ui/core/CardActions";
import { Divider } from "#material-ui/core";
import "bootstrap/dist/css/bootstrap.css";
const OrderTotal = () => {
const classes = useStyles();
return (
<div>
<Col sm={4}>
{" "}
<Card className={classes.root}>
<CardHeader title="Order Summary" className={classes.header} />
<Divider variant="middle" />
<CardContent>
<div className={classes.list}>
<Row>
<Col sm={6}>
<Typography align="center">Display Item</Typography>
</Col>
<Col sm={6}>
<Typography align="center">Display Prices</Typography>
</Col>
</Row>
</div>
</CardContent>
<Divider variant="middle" />
<CardActions className={classes.action}>
<Button variant="contained" color="primary" className={classes.button}>
Order Now
</Button>
</CardActions>
</Card>
</Col>
</div>
);
};
export default OrderTotal;
How do I implement this? How do I pass the prices and names to the order summary component and list them whenever they are added or deleted? I will really appreciate it as I can't seem to figure this out!
You need to store the current cart items in the redux state. You will need an action that adds an item to the cart. Your reducer needs to handle this action and update the cart data. Here is a very basic implementation:
const orderSlice = createSlice({
name: 'order',
initialState: {
items: [],
status: 'unsubmitted'
},
reducers: {
addToOrder: (state, action) => {
state.items.push(action.payload);
},
submitOrder: (state) => {
state.status = 'pending';
}
}
})
export const orderReducer = orderSlice.reducer;
export const {addToOrder, submitOrder} = orderSlice.actions;
Your "Add To Order" Button needs an onClick handler that dispatches your action.
<Button
variant="contained"
color="secondary"
onClick={() => dispatch(addToOrder({
name: restaurantInfo.itemName12,
price: restaurantInfo.itemPrice12
}))}
>
Add To Order
</Button>
Your OrderTotal component would use a useSelector hook to access the cart data from redux.
const orderItems = useSelector(state => state.order.items);
const orderTotal = orderItems.reduce((total, item) => total + item.price, 0);
As a sidenote, you probably should not store restaurantInfo in your component state since it seems like it's already being set in redux. Instead you should access it with a useSelector.
I have a Chakra UI Modal which opens up onClick of a button. I want to be able to extract the values that a user puts into the inputs/radio buttons when they close the Modal. The Modal class and the Modal/Button render is shown below. Since the input and radio buttons are defined within the Modal class, is it possible to get their final values onClose?
Modal.tsx
import React from 'react'
import {
Modal as ChakraModal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalFooter,
ModalBody,
ModalCloseButton,
RadioGroup,
Stack,
Radio,
VStack
} from "#chakra-ui/react"
import Button from './Button'
import Input from './Input'
type Props = { isOpen : boolean } & { onClose : () => void} & { label : string }
const Modal = ({ label, isOpen, onClose, ...rest }: Props) => (
<ChakraModal {...rest} isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>{label}</ModalHeader>
<ModalCloseButton />
<ModalBody>
<VStack spacing={4}>
<RadioGroup>
<Stack direction="row">
<Radio value="1">Annually</Radio>
<Radio value="2">Semi-Annual</Radio>
<Radio value="3">Quarterly</Radio>
<Radio value="4">Monthly</Radio>
</Stack>
</RadioGroup>
<Input
label="Custom Interest rate"
name="Custom Interest rate"
/>
</VStack>
</ModalBody>
<ModalFooter>
<Button colorScheme="blue" mr={3} onClick={onClose}>
Save
</Button>
</ModalFooter>
</ModalContent>
</ChakraModal>
)
export default Modal
Render
<Button onClick={onOpen}> Settings </Button>
<Modal
label="Custom Settings"
isOpen={isOpen}
onClose={onClose}
/>
You should probably send a state as the modal's prop.
const [state, setState] = React.useState();
<Modal
label="Custom Settings"
isOpen={isOpen}
onClose={onClose}
onChange={setState}
/>
To get the type of setState, hover over the variable and you can see the type definition.
I'm working on a React Project. I'm building a form with about 5 fields in it. I've used React Hooks to manage the state of the updates however when I enter in an input into the field. I can see the component re-render each time I enter a key stroke. the re-render is causing issues because it sets a state of a form field back to empty. Any help would be greatly appreciated!
Thanks,
Link to a gif of the re-render on keystroke can be found here: https://gph.is/g/ZxDqzmN
Link to clearing the form field: https://gph.is/g/4LjmDpd
import React, { useState } from "react";
import styled from "styled-components";
import {
Button,
CardContent,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Card as MuiCard,
Paper as MuiPaper,
TextField,
} from "#material-ui/core";
import { spacing } from "#material-ui/system";
export default function EmployeeFormDialog() {
const [open, setDialog] = useState(null);
const [carName, setCarName] = useState([""]);
const onSubmit = (data, event) => {
event.preventDefault();
console.log(data);
setDialog(false);
};
console.log("re-render");
const Card = styled(MuiCard)(spacing);
const Paper = styled(MuiPaper)(spacing);
return (
<Card mb={6}>
<CardContent>
<Paper mt={4}>
<div>
<Button variant="contained" color="primary" onClick={() => setDialog(true)}>
Add New Cars
</Button>
<Dialog open={open} aria-labelledby="form-dialog-title" disableEnforceFocus="true">
<form onSubmit={onSubmit}>
<DialogTitle id="form-dialog-title">Add New Car</DialogTitle>
<DialogContent>
<DialogContentText>To add new car</DialogContentText>
<TextField
onChange={(e) => setCarName(e.target.value)}
defaultValue={carName}
name="carName"
margin="dense"
id="carName"
label="Car Name"
type="text"
fullWidth
/>
<TextField
autoFocus
name="carYear"
margin="dense"
id="carYear"
label="Car Year"
type="text"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button type="button" onClick={() => setDialog(false)} color="primary">
Cancel
</Button>
<Button type="submit" color="primary">
Add Car
</Button>
</DialogActions>
</form>
</Dialog>
</div>
</Paper>
</CardContent>
</Card>
);
}
I'm trying to work with Hooks in react but i have a doubt about useState and References. My problem is because i want to create multiple references in my jsx but i dont know how use the usestate like a Array, well in the insert of the usestate data.
import React, { useState, useEffect } from "react";
import { Row, Col, Image, ListGroup, Container } from "react-bootstrap";
import AOS from "aos";
import "./css/App.css";
import "aos/dist/aos.css";
import Skills from "./Components/Skills";
import Work from "./Components/Work";
const App = () => {
const [ref, setRef] = useState([]);
useEffect(() => {
AOS.init({
duration: 2000
});
});
function handleOnClick(event) {
ref.scrollIntoView();
}
return (
<div className="App">
<Row>
<Col className="menu text-center" lg={4}>
<div className="picture">
<Image
src={process.env.PUBLIC_URL + "/Images/picture.jpg"}
roundedCircle
/>
</div>
<h1 className="menu-name">Fulanito Detal</h1>
<h4 className="menu-office">Software Engineer - Web Developer</h4>
<div>
<Row>
<Col lg={3}></Col>
<Col lg={6} className="menu-text">
<ListGroup>
<ListGroup.Item
onClick={event => handleOnClick(event)}
active
>
ABOUT
</ListGroup.Item>
<ListGroup.Item>WORK EXPERIENCE</ListGroup.Item>
<ListGroup.Item>EDUCATION</ListGroup.Item>
<ListGroup.Item>SKILLS</ListGroup.Item>
<ListGroup.Item>CONTACT</ListGroup.Item>
</ListGroup>
</Col>
<Col lg={3}></Col>
</Row>
</div>
</Col>
<Col className="info text-center" lg={8}>
<Container>
<div className="about"></div>
<div
className="work"
ref={ref => {
setRef(ref);
}}
>
<Work />
</div>
<div className="education"></div>
<div
className="skills"
ref={ref => {
setRef(ref);
}}
>
<Skills />
</div>
<div className="contact"></div>
</Container>
</Col>
</Row>
</div>
);
};
export default App;
The ref works fine just with one. If clicked about redirect to skills, but i want to use state like array to work with all references but i'm stuck with this one. Thanks for any help!
Here is a simplified example of using the useRef hook:
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const App = () => {
const work = React.useRef();
const skills = React.useRef();
return (
<div>
<button onClick={() => work.current.scrollIntoView()}>
WORK EXPERIENCE
</button>
<button onClick={() => skills.current.scrollIntoView()}>SKILLS</button>
<div className="another" />
<div className="work" ref={work}>
WORK SECTION
</div>
<div className="skills" ref={skills}>
SKILL SECTIONS
</div>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);