React cart empty function - javascript

I am new with react, I have a cart and I want it empty when a user place an order. I have a function that empties the cart "resetCartList" that I did in the context provider and it is already in Cart.jsx, but I do not know where to put it due to I have an onclick that already place the order. Below is the code:
This is the Cart.jsx:
import { useState } from "react";
import { Button, Col, Container, Form, Table } from "react-bootstrap";
import { Link } from "react-router-dom";
import { useCartContext } from "../../Context/CartContext";
import { getFirestore } from "../../firebase";
import firebase from "firebase/app";
import "firebase/firestore";
const CartComponent = ({ header = false }) => {
const {
list,
totalPrice,
deleteProd,
orderId,
setOrderId,
date,
setDate,
resetCartList,
} = useCartContext();
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [phone, setPhone] = useState("");
let datePurchase = new Date();
setDate(datePurchase.toLocaleString());
const placeOrder = () => {
let newOrder = {
Buyer: { name: name, email: email, phone: phone },
items: [...list],
Date: firebase.firestore.FieldValue.serverTimestamp(),
total: totalPrice(),
};
console.log("newOreder", newOrder);
const fsDB = getFirestore();
const orederCollection = fsDB.collection("orders");
orederCollection.add(newOrder).then((value) => {
setOrderId(value.id);
});
};
return (
<>
{!header && <h1 className="py-4 text-center text-muted">Cart</h1>}
{list.length > 0 ? (
<div>
<Container>
<Table striped hover className="text-muted">
<thead>
<tr>
<th>Product</th>
<th>Title</th>
<th>Quantity</th>
<th>Price</th>
{!header && <th> </th>}
</tr>
</thead>
<tbody>
{list.map((varietal) => (
<tr key={varietal.id}>
<td>
<img
src={varietal.image}
alt="img"
style={{ width: "82px" }}
/>
</td>
<td className="align-middle">{varietal.title}</td>
<td className="align-middle">{varietal.count}</td>
<td className="align-middle">${varietal.price}</td>
{!header && (
<td className="align-middle">
<button
onClick={() => deleteProd(varietal)}
className="badge badge-info"
>
Remove
</button>
</td>
)}
</tr>
))}
</tbody>
<tfoot>
<tr className="font-weight-bold h4 mr-5 pr-5">
<td colSpan={!header ? 4 : 3} className="text-right">
Total
</td>
<td className="mr-5 pr-5">${totalPrice()}</td>
</tr>
</tfoot>
</Table>
{!header && (
<div className="mr-5 pr-5">
<Form as={Col} className="mx-5 px-5 text-muted">
<Form.Group>
<Form.Label>Name</Form.Label>
<Form.Control
className="font-italic font-weight-lighter"
type="text"
placeholder="Enter name.."
onChange={(e) => {
setName(e.target.value);
}}
/>
</Form.Group>
<Form.Group>
<Form.Label>Email address</Form.Label>
<Form.Control
className="font-italic font-weight-lighter"
type="email"
placeholder="Enter email.."
onChange={(e) => {
setEmail(e.target.value);
}}
/>
</Form.Group>
<Form.Group>
<Form.Label>Telephone Number</Form.Label>
<Form.Control
className="font-italic font-weight-lighter"
type="tel"
placeholder="Enter telephone number.."
onChange={(e) => {
setPhone(e.target.value);
}}
/>
</Form.Group>
<Form.Text className="font-italic text-muted">
We'll never share your information with anyone else.
</Form.Text>
</Form>
<Link to="/PurchaseDone" orderId={orderId} date={date}>
<Button
variant="info"
className="mx-auto my-4 d-block"
size="lg"
onClick={() => {
placeOrder();
}}
>
Place order
</Button>
</Link>
</div>
)}
</Container>
</div>
) : (
<div>
<h3 className="d-flex justify-content-center pt-5 text-muted">
The Cart is empty
</h3>
{!header && (
<p className="d-flex justify-content-center text-muted">
Return to home to see our products
</p>
)}
{!header && (
<Link
to="/"
className="d-flex justify-content-center text-decoration-none"
>
<button className="btn btn-info"> Home </button>
</Link>
)}
</div>
)}
</>
);
};
export default CartComponent;
Thanks

You can call multiple functions in handlers with creating new function like this:
<Button
variant="info"
className="mx-auto my-4 d-block"
size="lg"
onClick={() => {
placeOrder();
resetCartList();
}}
>
Place order
</Button>

Related

How to pass value of inputs to other function?

I create multiple step button with useState hook and it work fine. Now I trying pass value of inputs from step two of button to step three. There is a problem I can't pass props or state in my function and I have error that state or props is undefined. I try more and more but give nothing.
This is my code :
const ShowOrNot = () => {
const [showForm, setShowForm] = useState(false);
const [showPreview, setShowPreview] = useState(false);
const [formHidden, setFormHidden] = useState(false);
return (
<div className="col-12">
{!showForm ? (
<ShowFormButton onClick={() => setShowForm(true)}/>
) : undefined}
{showForm ? (
<div className={''} id="scrollbar-style">
<div>
<HideFormButton
onClick={() => {
setShowForm(false);
}}
/>
</div>
{!formHidden ? <MyForm/> : undefined}
{!showPreview ? (
<ShowPreviewButton
onClick={() => {
setShowPreview(true);
setFormHidden(true);
}}
/>
) : undefined}
{showPreview ? (
<div className={"preview-send-wrapper"}>
<div className={"preview-send-header"}>
<div className={"preview-send-header-icon"}>
</div>
<h2>
Preview
</h2>
</div>
<div className={"mt-5 preview-send-cover"}>
<img src={value of inputs} alt={"cover"}/>
</div>
<div className={" preview-send-video-poster"}>
<img src={value of inputs} alt={"cover"}/>
<h1 className={"mt-4"}>
{this.props.videoTitle} // one value of inputs get here
<span>{two value of inputs get here}</span>
</h1>
<h4 className={"mt-3"}>
{value of inputs}
</h4>
</div>
<div className={"preview-send-summary-video"}>
<p>
{value of inputs}
</p>
</div>
<Row>
<div className={"col-lg-8 col-12"}>
<button className={"send-video-btn-final"}>
Send
</button>
</div>
<div className={"col-lg-4 col-12"}>
<SendButton
onClick={() => {
setFormHidden(false);
setShowPreview(false);
setShowForm(true);
}}
/>
</div>
</Row>
</div>
) : undefined}
</div>
) : undefined}
</div>
);
};
function SendButton({onClick}) {
return (
<div>
<button className="edit-send-video-btn w-100" onClick={onClick}>
Edit
</button>
</div>
);
}
function ShowFormButton({onClick}) {
return (
<div>
<button className="upload-content-btn w-100" onClick={onClick}>
<span className="ml-2">
</span>new upload{' '}
</button>
</div>
);
}
function ShowPreviewButton({onClick}) {
return (
<div className={"row show-preview-button"}>
<div className="col-lg-8 col mt-3">
<button className="preview-send-data-btn" onClick={onClick}>
Preview
</button>
</div>
<div className="col-lg-4 col mt-3">
<button className="draft-send-data-btn">Draft</button>
</div>
</div>
);
}
function HideFormButton({onClick}) {
return (
<div className={'content-send-form-close-btn'}>
<button onClick={onClick} className={'close-modal-btn'}>
<span>Close</span>
</button>
</div>
);
}
class MyForm extends Component {
constructor(props) {
super(props);
this.state = {
videoTitle: "",
category: "",
summary: "",
videoText: "",
}
}
onChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
});
};
render() {
return (
<div className={"content-send-form-wrapper"}>
<div className={'content-send-form-header'}>
<div className={'content-send-form-header-title'}>
</div>
</div>
<form className={'mt-3 content-send-form-data register-teacher-inputs-box '}>
<Row>
<div className={'col-lg-6 col-12 mt-4'}>
<label htmlFor={'name'} className={' text-right'}>
<span>*</span>
</label>
<input
type="text"
className="form-control"
placeholder={'Title'}
name={'videoTitle'}
required="true"
value={this.state.videoTitle}
onChange={this.onChange}
onBlur={(e) => (e.target.placeholder = 'Title')}
onFocus={(e) => (e.target.placeholder = '')}
/>
</div>
<div className={'col-lg-6 col-12 mt-4'}>
<label htmlFor={'country'} className={' text-right'}>
<span>*</span>
</label>
<input
type="text"
className="form-control"
placeholder={'category'}
name={'category'}
value={this.state.category}
onChange={this.onChange}
required="true"
onBlur={(e) => (e.target.placeholder = 'category')}
onFocus={(e) => (e.target.placeholder = '')}
/>
</div>
</Row>
<Row>
<div className="col-12 mt-3 video-upload-input-btn">
<VideoUpload/>
</div>
</Row>
<Row>
<div className="col-lg-6 col-12 mt-3">
<PosterUpload/>
</div>
<div className="col-lg-6 col-12 mt-3">
<CoverUpload/>
</div>
</Row>
</form>
</div>
);
}
}

Closing a modal on clicking outside it with React Hooks

I'm trying to create a pop up subscription box which closes whenever one clicks on the close button or clicks anywhere outside the pop up. I've created a modal component and a state showModal which is used to toggle the visibility of this Modal. I have tried to add setShowModal(false) to the outer div element but that just disables the whole modal. What can be done to close the modal whenever we click outside the modal. This is how my main page looks
const [showModal, setShowModal] = useState(false);
return (
<>
<div
className="homepage"
style={{
filter: showModal ? "blur(8px)" : "none",
minHeight:"80vh",
}}
>
<section
className="homepage-hero"
style={{ paddingBottom:"-2rem", minHeight:"100vh" }}
>
<div className="hero-body">
<div className="container">
<div className="columns">
<div className="column ">
<h1>
<span className="heading">
Finance <br />
Scheme
</span>
<br />
</h1>
<p>
Lorem Ipsum
</p>
<div className="is-hidden-tablet">
</div>
<div className="button-group">
<button
style={{
fontWeight: "600",
padding: "0.75em 1.9em",
borderRadius: "0px",
color: "white",
backgroundColor: "#24ca7a",
border: "1px solid #24ca7a",
cursor: "pointer",
}}
onClick={() => setShowModal(true)}
>
Download
</button>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
{showModal && (
<Modal
modalId="signup-modal"
onClose={() => setShowModal(false)}
canDismiss={false}
modalWidth="70%"
style={{position:"fixed", top:"20", minHeight:"50vh"}}
>
<div className="contact-us" style={{ margin:"20px"}}>
<section className="contact-form" >
<div className="container">
<div className="columns is-8 ">
<div
className="column is-half-desktop is-full-mobile container-content"
style={{ boxShadow: "none" }}
>
{submitted ? (
<div className="success">
<img src={confirmedIllus} alt="" />
<h2>Your details have been submitted successfully!</h2>
</div>
) : (
<form onSubmit={handleOnSubmit} id="contact-form" >
<h1 className="heading" style={{ fontSize: "2rem" }}>
Your Details
</h1>
<br />
<div className="field">
<label className="label">Name</label>
<div className="control">
<input
className="input"
id="name"
value={name}
type="text"
placeholder="Your Full Name"
onChange={(e) => setName(e.target.value)}
required
/>
</div>
</div>
<div className="field">
<label className="label">Email</label>
<div className="control ">
<input
className={`input ${isDanger}`}
id="email"
value={email}
type="email"
onChange={handleOnChange}
placeholder="Your Email"
required
/>
{!validEmail && isDanger ? (
<span className="icon is-small is-right">
<i className="material-icons-round">warning</i>
</span>
) : (
" "
)}
</div>
{!validEmail && isDanger ? (
<p className="help is-danger">{emailMessage}</p>
) : (
""
)}
</div>
<div className="field is-grouped submit-button-group">
<div className="control">
<button
style={{
cursor: !validEmail ? "not-allowed" : "pointer",
}}
className="button submit-button"
id="submit-form"
>
Submit
</button>
</div>
</div>
</form>
)}
</div>
<div className="column is-half-desktop is-full-mobile " >
<img
src="/images/Ebook.svg"
className="is-hidden-mobile"
style={{ width: "70%", marginTop: "40%" }}
/>
<div className=" font-blue bottom-text">
Fill your details to download the free <b> Ebook </b>
</div>
</div>
</div>
</div>
</section>
</div>
</Modal>
)}
</>
);
You can use the useOnClickOutside hook. This hook allows you to detect clicks outside of a specified element.
You have to import the followings
Create a ref that we add to the element for which we want to detect outside clicks
const ref = useRef();
State for our modal
const [showModal, setShowModal] = useState(false);
Call hook passing in the ref and a function to call on outside click
useOnClickOutside(ref, () => setShowModal(false));
render here
return(...);
//Hook
import { useEffect } from 'react';
export default function useOnClickOutside(ref, handler) {
useEffect(
() => {
const listener = (event) => {
// Do nothing if clicking ref's element or descendent elements
if (!ref.current || ref.current.contains(event.target)) {
return;
}
handler(event);
};
document.addEventListener("mousedown", listener);
document.addEventListener("touchstart", listener);
return () => {
document.removeEventListener("mousedown", listener);
document.removeEventListener("touchstart", listener);
};
},
// Add ref and handler to effect dependencies
// It's worth noting that because the passed-in handler is a new ...
// ... function on every render that will cause this effect ...
// ... callback/cleanup to run every render. It's not a big deal ...
// ... but to optimize you can wrap handler in useCallback before ...
// ... passing it into this hook.
[ref, handler]
);
}
See related repl output here - https://spanishhotloaderprogram.thelovekesh.repl.co/
For this, you can give tabIndex=-1 to your modal div, and then you can use the onBlur event.
const [showModal, setShowModal] = useState(false);
return (
<>
<div
className="homepage"
style={{
filter: showModal ? "blur(8px)" : "none",
minHeight:"80vh",
}}
>
<section
className="homepage-hero"
style={{ paddingBottom:"-2rem", minHeight:"100vh" }}
>
<div className="hero-body">
<div className="container">
<div className="columns">
<div className="column ">
<h1>
<span className="heading">
Finance <br />
Scheme
</span>
<br />
</h1>
<p>
Lorem Ipsum
</p>
<div className="is-hidden-tablet">
</div>
<div className="button-group">
<button
style={{
fontWeight: "600",
padding: "0.75em 1.9em",
borderRadius: "0px",
color: "white",
backgroundColor: "#24ca7a",
border: "1px solid #24ca7a",
cursor: "pointer",
}}
onClick={() => setShowModal(true)}
>
Download
</button>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
{showModal && (
<Modal
modalId="signup-modal"
onBlur={() => setShowModal(false)}
canDismiss={false}
modalWidth="70%"
style={{position:"fixed", top:"20", minHeight:"50vh"}}
tabIndex={-1}
>
<div className="contact-us" style={{ margin:"20px"}}>
<section className="contact-form" >
<div className="container">
<div className="columns is-8 ">
<div
className="column is-half-desktop is-full-mobile container-content"
style={{ boxShadow: "none" }}
>
{submitted ? (
<div className="success">
<img src={confirmedIllus} alt="" />
<h2>Your details have been submitted successfully!</h2>
</div>
) : (
<form onSubmit={handleOnSubmit} id="contact-form" >
<h1 className="heading" style={{ fontSize: "2rem" }}>
Your Details
</h1>
<br />
<div className="field">
<label className="label">Name</label>
<div className="control">
<input
className="input"
id="name"
value={name}
type="text"
placeholder="Your Full Name"
onChange={(e) => setName(e.target.value)}
required
/>
</div>
</div>
<div className="field">
<label className="label">Email</label>
<div className="control ">
<input
className={`input ${isDanger}`}
id="email"
value={email}
type="email"
onChange={handleOnChange}
placeholder="Your Email"
required
/>
{!validEmail && isDanger ? (
<span className="icon is-small is-right">
<i className="material-icons-round">warning</i>
</span>
) : (
" "
)}
</div>
{!validEmail && isDanger ? (
<p className="help is-danger">{emailMessage}</p>
) : (
""
)}
</div>
<div className="field is-grouped submit-button-group">
<div className="control">
<button
style={{
cursor: !validEmail ? "not-allowed" : "pointer",
}}
className="button submit-button"
id="submit-form"
>
Submit
</button>
</div>
</div>
</form>
)}
</div>
<div className="column is-half-desktop is-full-mobile " >
<img
src="/images/Ebook.svg"
className="is-hidden-mobile"
style={{ width: "70%", marginTop: "40%" }}
/>
<div className=" font-blue bottom-text">
Fill your details to download the free <b> Ebook </b>
</div>
</div>
</div>
</div>
</section>
</div>
</Modal>
)}
</>
);
In your div className homepage you can use a condition when you click, if showModal is true --> setShowModal to false like
<div
className="homepage"
style={{
filter: showModal ? "blur(8px)" : "none",
minHeight: "80vh",
}}
onClick={() => showModal && setShowModal(false)}
>

OnClick Javascript function is not working in reactjs

I have a login page and below shown the jsx of my login page .Login submit button is inside here.on clicking this login button nothin is triggered or no change reflected
const SectionLogin = ({ onLoginClick, setEmail, setPassword }) => {
return (
<>
<div
className='wrapper'
style={{
backgroundImage: 'url(' + require('app/assets/img/j.jpg') + ')',
}}
>
<Container>
<Row>
<Col
className='mx-auto'
lg='4'
md='6'
style={{ paddingTop: '60px' }}
>
<Card className='card-register' style={{ padding: '15px' }}>
<h3 className='title mx-auto'>Welcome</h3>
<div className='social-line text-center'>
<Button
className='btn-neutral btn-just-icon mt-0'
color='facebook'
// onClick={(e) => e.preventDefault()}
>
<i
className='fab fa-facebook fa-3x'
style={{ color: '#3b5998' }}
/>
</Button>
<Button
className='btn-neutral btn-just-icon mt-0 ml-1'
color='google'
// onClick={(e) => e.preventDefault()}
>
<i
className='fab fa-google-plus fa-3x'
style={{ color: '#db4a39' }}
/>
</Button>
<Button
className='btn-neutral btn-just-icon mt-0 ml-1'
color='twitter'
// onClick={(e) => e.preventDefault()}
>
<i
className='fab fa-twitter fa-3x'
style={{ color: '#00acee' }}
/>
</Button>
</div>
<Form className='register-form'>
<label>Email</label>
<InputGroup className='form-group-no-border'>
<InputGroupAddon addonType='prepend'>
<InputGroupText>
<i className='nc-icon nc-email-85' />
</InputGroupText>
</InputGroupAddon>
<Input
placeholder='Email'
type='email'
// onChange={(e) => setEmail(e.target.value)}
/>
</InputGroup>
<label>Password</label>
<InputGroup className='form-group-no-border'>
<InputGroupAddon addonType='prepend'>
<InputGroupText>
<i className='nc-icon nc-key-25' />
</InputGroupText>
</InputGroupAddon>
<Input
placeholder='Password'
type='password'
// onChange={(e) => setPassword(e.target.value)}
/>
</InputGroup>
<Button
block
className='btn-round'
color='warning'
type='button'
onClick={onLoginClick}
>
Login
</Button>
</Form>
<div className='forgot'>
<Button
className='btn-link'
color='secondary'
// onClick={(e) => e.preventDefault()}
>
Forgot password?
</Button>
</div>
</Card>
<div className='col text-center'>
{/* <Button
className='btn-round'
outline
color='neutral'
href='/register-page'
size='lg'
target='_blank'
>
View Register Page
</Button> */}
</div>
</Col>
</Row>
</Container>
</div>
</>
);
};
export default SectionLogin;
button code is inside this SectionLogin Container(inside return where my login page jsx reside)
import React, { useEffect, useCallback, useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import SectionLogin from './LoginPage';
const LoginContainer = () => {
const dispatch = useDispatch();
const onLoginClick = (e) => {
console.log('hereeee');
alert('Hello');
};
return (
<>
<div className='content'>
<SectionLogin
onLoginClick={onLoginClick}
/>
</div>
</>
);
};
export default LoginContainer;
onLoginClick function is not triggering when button is clicked.
Can you try this,
<Button
block
className="btn-round"
color="warning"
type="button"
onClick={(event)=>onLoginClick(event)}>
Login
</Button>;
Hope this helps!!
Pass your onClick function as onLoginClick
<div className='content'>
<SectionLogin
onLoginClick={onLoginClick}
/>
</div>
And use it as
<Button
block
className="btn-round"
color="warning"
type="button"
onClick={() => onLoginClick() }
>
Login
</Button>;

Custom React component(react-hook) not re-rendering

I have a component that fetches data from my mongoDB it then renders a list of child components. It the "list" component I have a post that adds a new member to the database. Upon addition im trying to get the list to re-fetch the data and re-render the list component.
List Component:
import React, { useState, useEffect } from "react";
import axios from "axios";
import Spinner from "react-bootstrap/Spinner";
import { toast } from "react-toastify";
import DatePicker from "react-datepicker";
import useForm from "react-hook-form";
import { css } from "glamor";
import "react-toastify/dist/ReactToastify.css";
import "react-datepicker/dist/react-datepicker.css";
import "../Styles/ReactDatePicker.css";
import Member from "./Member";
const { getFamily, getMembers, postMember } = require("../Utils/Service");
const MemberList = () => {
const [family, setFamily] = useState({});
const [familyMembers, setFamilyMembers] = useState([]);
const [loading, setLoading] = useState(true);
const [date, setDate] = useState(new Date());
const { handleSubmit, register, errors } = useForm();
async function fetchData() {
getFamily.then(result => {
setFamily(result);
});
getMembers.then(result => {
try {
setFamilyMembers(
result.map((child, index) => (
<Member
key={index}
index={child._id}
balance={child.balance}
firstName={child.firstName}
lastName={child.lastName}
birthday={child.birthday}
role={child.role[0]}
/>
))
);
} catch (e) {
toast.error("500: Error with Service Call", {
position: "top-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
className: css({
background: "#ed5565 !important"
})
});
} finally {
setLoading(false);
}
});
}
useEffect(() => {
if (loading) {
fetchData();
}
}, [loading]);
// const handleDateChange = date => {
// setDate(date)
// }
const onSubmit = data => {
data.familyId = "5dddf14df965552b3da57be1";
postMember(data).then(
????????????
);
};
return (
<div className="ibox">
<div className="ibox-title">
<h5>{family.name}</h5>
<div className="ibox-tools">
<span className="label label-warning-light float-right">
{familyMembers.length} Member(s)
</span>
</div>
</div>
<div className="ibox-content">
<div className="feed-activity-list">
{loading ? (
<Spinner animation="grow" role="status" variant="dark">
<span className="sr-only">Loading...</span>
</Spinner>
) : (
familyMembers
)}
</div>
<div className="d-flex">
<a
className="btn btn-primary text-white m-t"
data-toggle="modal"
data-target={"#newMemberModel"}
>
<i className="fa fa-plus"></i> New Member
</a>
<a
className="btn btn-danger text-white m-t m-l"
data-toggle="modal"
data-target={"#removeMemberModel"}
>
<i className="fa fa-minus"></i> Remove Member
</a>
</div>
</div>
{/* New Member Model */}
<div
className="modal inmodal"
id={"newMemberModel"}
tabIndex="-1"
role="dialog"
style={{ display: "none" }}
aria-hidden="true"
>
<div className="modal-dialog">
<div className="modal-content animated fadeIn">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal">
<span aria-hidden="true">×</span>
<span className="sr-only">Close</span>
</button>
<h4 className="modal-title">New Family Member</h4>
</div>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="modal-body">
<div className="row">
<div className="col">
<div className="form-group">
<label>First Name</label>
<input
type="text"
placeholder="First Name"
className="form-control"
name="firstName"
ref={register({
required: true,
pattern: {
value: /^[a-zA-Z]+$/i,
message: "Invalid First Name"
}
})}
/>
<div className="text-danger">
{errors.firstName && errors.firstName.message}
</div>
</div>
<div className="form-group">
<label className="font-normal">Birthday</label>
<div className="input-group date">
{/* <DatePicker
selected={date}
onChange={handleDateChange}
placeholderText="Click to select a date"
isClearable
peekNextMonth
showMonthDropdown
showYearDropdown
dropdownMode="select"
ref={e =>register({
name: "Birthday",
required: false
})}
/> */}
<input
type="text"
placeholder="01/01/01"
className="form-control"
name="birthDate"
ref={register({
required: false
})}
/>
</div>
</div>
</div>
<div className="col">
<div className="form-group">
<label>Last Name</label>
<input
type="text"
placeholder="Last Name"
className="form-control"
name="lastName"
ref={register({
required: true,
pattern: {
value: /^[a-zA-Z]+$/i,
message: "Invalid Last Name"
}
})}
/>
<div className="text-danger">
{errors.lastName && errors.lastName.message}
</div>
</div>
<div className="form-group">
<label>Role</label>
<select
className="custom-select"
name="role"
ref={register({ required: true })}
>
<option defaultValue>Select Role</option>
<option value="Adult">Adult</option>
<option value="Child">Child</option>
</select>
</div>
</div>
</div>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-white"
data-dismiss="modal"
>
Close
</button>
<button type="submit" className="btn btn-primary">
Add Member
</button>
</div>
</form>
</div>
</div>
</div>
{/* Remove Member Model */}
<div
className="modal inmodal"
id={"removeMemberModel"}
tabIndex="-1"
role="dialog"
style={{ display: "none" }}
aria-hidden="true"
>
<div className="modal-dialog">
<div className="modal-content animated fadeIn">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal">
<span aria-hidden="true">×</span>
<span className="sr-only">Close</span>
</button>
<h4 className="modal-title">Remove Family Member</h4>
</div>
<div className="modal-body"></div>
<div className="modal-footer">
<button
type="button"
className="btn btn-white"
data-dismiss="modal"
>
Close
</button>
<button type="button" className="btn btn-danger">
Remove Member
</button>
</div>
</div>
</div>
</div>
</div>
);
};
export default MemberList;
within the code in the onSubmit function with posts the data inside the .then is where im trying to re-render the entire component and/or fetch the data agin.
right now, your useEffect is only dependent on the property loading, if you change the property then the effect will run again.
https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect
In your component, you can call this.forceUpdate() to force a rerender.
I think you can also call your fetchData function again inside your .then() block, if you make the callback inside the .then() an async function.
postMember(data).then(
async () => this.fetchData()
);
or
postMember(data).then(
() => this.forceUpdate()
);

Setting Component State after Redux has Mapped Redux State to Props

I am trying to initialize a form with some user information using Redux Forms by pulling the information from my components state. I have a redux action in the componentDidMount method of my component that calls the action, retrieves the information, and then maps a 'profile' object from my store to the components props. The problem is, when I go to setState to update the profile info, it comes back as undefined. I have tried to use the componentWillRecieveProps to see if I can catch the updated 'Profile' props but it is still undefined. Whats the best way to update the component's state once 'this.props.profile' returns the users information?
Here is the component's code:
import React, { Component } from "react";
import { connect } from "react-redux";
import { Field, reduxForm } from "redux-form";
import { Link } from "react-router-dom";
import classnames from "classnames";
import * as actions from "../../actions";
class CreateProfile extends Component {
constructor(props) {
super(props);
this.state = {
showSocialMedia: true,
profile: {}
};
}
componentDidMount() {
this.props.getCurrentUserProfile();
}
// componentDidUpdate(prevProps, prevState) {
// if (prevProps.profile.profile !== this.props.profile.profile) {
// console.log(this.props.profile);
// }
// }
renderField(field) {
return (
<div className="form-group">
<input
className={classnames("form-control form-control-lg", {
"is-invalid": field.meta.touched && !field.meta.valid
})}
type={field.type}
placeholder={field.placeholder}
{...field.input}
/>
<small className="text-muted">{field.description}</small>
<div className="invalid">
{field.meta.touched && !field.meta.valid ? (
<div className="text-center">
<i className="far fa-edit" /> {field.meta.error}
</div>
) : (
""
)}
</div>
</div>
);
}
renderAlert() {
if (this.props.errors.message) {
return (
<div className="alert alert-danger error-message mt-4 text-center">
<h3>
<i className="fas fa-info-circle" />
</h3>
<h6 className="invalid">{this.props.errors.message}</h6>
</div>
);
}
}
renderSelectField(field) {
return (
<div className="form-group">
<select
className={classnames("form-control form-control-lg", {
"is-invalid": field.meta.touched && !field.meta.valid
})}
{...field.input}
>
<option value="" disabled>
* Select a Professional Status
</option>
<option value="Developer">Developer</option>
<option value="Junior Developer">Junior Developer</option>
<option value="Senior Developer">Senior Developer</option>
<option value="Manager">Manager</option>
<option value="Student or Learning">Student or Learning</option>
<option value="Instructor or Teacher">Instructor or Teacher</option>
<option value="Intern">Intern</option>
<option value="Other">Other</option>
</select>
<small className="text-muted">
Give us an idea of where you are at in your career
</small>
<div className="invalid">
{field.meta.touched && !field.meta.valid ? (
<div className="text-center">
<i className="far fa-edit" /> {field.meta.error}
</div>
) : (
""
)}
</div>
</div>
);
}
renderSocialMediaField(field) {
return (
<div className="form-group">
<div className="input-group-prepend">
<span className="input-group-text">
<i className={field.icon} />
</span>
<input
type={field.type}
className="form-control"
placeholder={field.placeholder}
icon={field.icon}
{...field.input}
/>
</div>
</div>
);
}
onSubmit(values) {
this.props.createNewUserProfile(values);
}
toggleHiddenSocialInputs(e) {
e.preventDefault();
this.setState({
showSocialMedia: !this.state.showSocialMedia
});
}
render() {
const { handleSubmit } = this.props;
const { profile } = this.props;
return (
<div className="container">
<div className="row">
<div className="col-md-8 m-auto">
<Link to="/dashboard" className="btn btn-light p-2 mt-2">
<i className="mr-1 fas fa-long-arrow-alt-left" /> Go Back
</Link>
<h5 className="display-4 pt-2 text-center font-weight-light">
Update Your Profile
</h5>
<p className="text-black-50 pt-3 font-weight-light">
* = required field
</p>
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
{this.renderAlert()}
<Field
name="handle"
type="text"
placeholder="* Profile handle"
component={this.renderField}
description="A unique handle for your profile URL - (Can't be changed later)"
/>
<Field name="status" component={this.renderSelectField} />
<Field
name="company"
type="text"
placeholder="Company"
component={this.renderField}
description="Can be your own or the one you work for"
/>
<Field
name="website"
type="text"
placeholder="Website"
component={this.renderField}
description="Could be your own or company website"
/>
<Field
name="location"
type="text"
placeholder="Location"
component={this.renderField}
description="Suggested format is: City, State"
/>
<Field
name="skills"
type="text"
placeholder=" Skills"
component={this.renderField}
description="Please use comma separated values (eg: HTML, CSS, Javascript, etc)"
/>
<Field
name="githubusername"
type="text"
placeholder="Github Username"
component={this.renderField}
description="If you want your latest repos and a Github link, include your username"
/>
<div className="form-control-group">
<Field
className="form-control form-control-lg"
name="bio"
placeholder="A short bio about yourself"
component="textarea"
/>
<small className="text-muted">
Tell us a little about yourself
</small>
</div>
<div className="row mt-2 pt-2">
<button
className="btn btn-outline-secondary m-auto"
onClick={this.toggleHiddenSocialInputs.bind(this)}
>
Add Social Network Links <i className=" ml-1 fas fa-users" />
</button>
</div>
{!this.state.showSocialMedia && (
<div className="mt-3">
<Field
name="facebook"
placeholder="Facebook profile URL"
icon="fab fa-facebook-square"
component={this.renderSocialMediaField}
/>
<Field
name="twitter"
placeholder="Twitter profile URL"
icon="fab fa-twitter-square"
component={this.renderSocialMediaField}
/>
<Field
name="linkedin"
placeholder="Linkedin profile URL"
icon="fab fa-linkedin"
component={this.renderSocialMediaField}
/>
<Field
name="youtube"
placeholder="Youtube profile URL"
icon="fab fa-youtube-square"
component={this.renderSocialMediaField}
/>
<Field
name="instagram"
placeholder="Instagram profile URL"
icon="fab fa-instagram"
component={this.renderSocialMediaField}
/>
</div>
)}
<button action="submit" className="btn btn-info btn-block mt-5">
Create Profile <i className=" ml-1 fas fa-user-alt" />
</button>
{this.renderAlert()}
</form>
</div>
</div>
</div>
);
}
}
function validate(values) {
const errors = {};
if (!values.handle) {
errors.handle = "Please enter a handle for your profile";
}
if (!values.status) {
errors.status = "Please select a status for your profile";
}
return errors;
}
const mapStateToProps = state => {
return {
errors: state.errors,
profile: state.profile
};
};
export default reduxForm({
validate,
form: "CreateProfile",
initialValues: {}
})(connect(mapStateToProps, actions)(CreateProfile));
First, I'm not sure why you want to attach profile to component state. But if this.props.profile is always undefined, then it sounds like you're failing to fetch the user profile or you're not updating the store correctly. I would need to see getCurrentUserProfile and your reducer.
Fwiw, I would dispatch a request for user information from a container and set initialValues to state.profile (if state.profile, is in fact, your initial user data).

Categories

Resources