Page not re-rendering after hook state update - reactjs

The page renders the input correctly, however errors only seem to appear on the second render even though they are displayed is useForm state on the first render.
So for the password field I enter a single character and the state of useForm changes to {password: "Must be at.....} but the screen does not update to display errors.password until I enter in another character.
// nodejs library that concatenates classes
// reactstrap components
import {
Button,
Card,
CardBody,
CardHeader,
Col,
Container,
Form,
FormFeedback,
FormGroup,
Input,
Row
} from "reactstrap";
import {register} from "apiCalls/AuthRequests";
import useForm from "hooks/AuthHooks";
import {registerFormValidation} from "components/validation/AuthFormValidation";
function RegisterForm(props) {
const [loading, setLoading] = useState(false);
const {values, handleChange, handleSubmit, errors, setErrors} = useForm(submit, registerFormValidation);
const emailRef = useRef(null);
const passwordRef = useRef(null);
const accessCodeRef = useRef(null);
async function submit() {
setLoading(true);
const response = await register(values.email, values.password, values.accessCode);
if (response.ok) {
} else if (response.status === 422) {
if ("access_code" in response.data) {
accessCodeRef.current.focus();
setErrors({accessCode: response.data.access_code});
}
if ("email" in response.data) {
setErrors({email: response.data.email});
emailRef.current.focus();
}
if ("password" in response.data) {
setErrors({password: response.data.password});
passwordRef.current.focus();
}
}
setLoading(false)
}
useEffect(() => {
console.log(errors);
});
return (
<>
<div className="content">
<Container className="pb-5">
<Row>
<Col lg="6" md="8" className="ml-auto mr-auto">
<Card className="bg-secondary border-0">
<CardHeader className="bg-transparent">
<div className="text-center">
<h2>Register</h2>
</div>
</CardHeader>
<CardBody className="px-lg-5 py-lg-5">
<Form role="form" onSubmit={handleSubmit}>
<FormGroup>
<label
className="form-control-label"
>
Email
</label>
<Input
name="email"
type="email"
innerRef={emailRef}
value={values.email || ""}
onChange={handleChange}
invalid={!!errors.email}
required
/>
<FormFeedback>{errors.email}</FormFeedback>
</FormGroup>
<FormGroup>
<label
className="form-control-label"
>
Password
</label>
<Input
name="password"
type="password"
innerRef={passwordRef}
value={values.password || ""}
onChange={handleChange}
invalid={!!errors.password}
required
/>
<FormFeedback>{errors.password}</FormFeedback>
</FormGroup>
<FormGroup>
<label
className="form-control-label"
>
Access Code
</label>
<Input
name="accessCode"
type="text"
innerRef={accessCodeRef}
value={values.accessCode || ''}
onChange={handleChange}
invalid={!!errors.accessCode}
required
/>
<FormFeedback>{errors.accessCode}</FormFeedback>
</FormGroup>
<Row className="my-4">
<Col xs="12">
<div
className="custom-control custom-control-alternative custom-checkbox">
<input
className="custom-control-input"
id="customCheckRegister"
type="checkbox"
required
/>
<label
className="custom-control-label"
htmlFor="customCheckRegister"
>
<span className="text-muted">
I agree with the{" "}
<a
href=""
target="_blank"
rel="noopener noreferrer"
>
Privacy Policy
</a>
</span>
</label>
</div>
</Col>
</Row>
<div className="text-center">
<Button disabled={loading} className="mt-4" color="info" type="submit">
Create account
</Button>
</div>
</Form>
</CardBody>
</Card>
</Col>
<Col md="4" className="ml-auto mr-auto">
<h2>Being a photographer is easier with <b className="text-primary">FOCAL</b></h2>
<ul>
<li>
<h4>Focal is great</h4>
</li>
<li>
<h4>Save time</h4>
</li>
<li>
<h4>More customers</h4>
</li>
</ul>
</Col>
</Row>
</Container>
</div>
</>
);
}
export default RegisterForm;
const useForm = (callback, validate) => {
const [values, setValues] = useState({});
const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = (event) => {
if (event) event.preventDefault();
setIsSubmitting(true);
};
useEffect(() => {
if (Object.keys(errors).length === 0 && isSubmitting) {
callback();
setIsSubmitting(false);
}
}, [callback, errors, isSubmitting]);
useEffect(() => {
setErrors(validate(values, errors));
}, [validate, values, errors]);
const handleChange = (event) => {
event.persist();
setValues(values => ({...values, [event.target.name]: event.target.value}));
setErrors(validate(values, errors));
};
return {
handleChange,
handleSubmit,
setErrors,
values,
errors
}
};
export default useForm;
export function registerFormValidation(values, errors) {
if (values.email === ""){
delete errors.email;
}
if (values.password) {
if (!verifyLength(values.password, PASSWORD_LENGTH)){
errors.password = "Password must be greater than 8 Characters";
} else {
delete errors.password;
}
}
if (values.accessCode === "") {
delete values.accessCode;
}
return errors
}```

I can appreciate that it's of interest to work on a custom hook but forms are ubiquitous and there are solid, proven means to work with them. IMHO Formik is probably the best.
With the three fields that you have there, you could implement something like the following:
import React from 'react';
import { Formik } from 'formik';
const BasicExample = () => (
<div>
<Formik
initialValues={{ email: '', password: '', accessCode: '' }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
render={props => (
<form onSubmit={props.handleSubmit}>
<input
type="email"
onChange={props.handleChange}
onBlur={props.handleBlur}
value={props.values.email}
name="email"
/>
{props.errors.email && <div id="feedback">{props.errors.email}</div>}
<input
type="password"
onChange={props.handleChange}
onBlur={props.handleBlur}
value={props.values.password}
name="password"
/>
{props.errors.password && <div id="feedback">{props.errors.password}</div>}
<input
type="text"
onChange={props.handleChange}
onBlur={props.handleBlur}
value={props.values.accessCode}
name="accessCode"
/>
{props.errors.accessCode && <div id="feedback">{props.errors.acessCode}</div>}
<button type="submit">Submit</button>
</form>
)}
/>
</div>
);
Note that the above is just from memory - which to some extent speaks to it's simplicity. As initialValues are supplied to Formik, you can build complex component hierarchies without having to pass down form state but that's just one of the various benefits.

I have an assumption.
In registerFormValidation doesn't modify errors object. Create a new each time.

FIXED:
const useForm = (callback, validate) => {
const [values, setValues] = useState({});
const [errors, setErrors] = useState({});
const handleSubmit = (event) => {
if (event) event.preventDefault();
if (Object.keys(errors).length === 0){
callback();
}
};
const handleChange = (event) => {
event.persist();
setValues(values => ({...values, [event.target.name]: event.target.value}));
setErrors(validate({[event.target.name]: event.target.value}, errors));
};
return {
handleChange,
handleSubmit,
setErrors,
values,
errors
}
};
export default useForm;
got rid of useEffect!

Related

Why do i get error 400 on my graphQL mutation create user

I'm working with Reactjs and GraphQL integration. i got a problem when i'm doing mutation for new user.
Scenario :
Creating user using Modals bootstrap. when successful create new user, it shows alert or information success.
Code :
Here's my ModalCreate component code.
import React, { useState, useEffect } from 'react';
import { Button, Modal, Form } from "react-bootstrap";
const ModalCreate = (props) => {
// state for check input component
const [value, setValue] = useState({
username: props.username || '',
email: props.email || '',
fullname: props.full_name || '',
password: props.password || '',
phone: props.phone || '',
address: props.address || '',
groupid: props.group_id,
});
const onChange = event => {
setValue({
...value,
[event.target.name]: event.target.value
})
}
useEffect(() => {
if (props.show) {
document.body.classList.add("modal-open");
}
return () => {
if (document.body.classList.contains("modal-open")) {
document.body.classList.remove("modal-open");
}
};
}, [props.show]);
return (
<Modal show={props.show}>
<Modal.Header>
<Modal.Title> <span>FORMULIR AKUN PENGGUNA</span> </Modal.Title>
</Modal.Header>
<Modal.Body>
<Form onSubmit={e => {
e.preventDefault();
props.action({
variables: {
...value
}
})
}}>
<Form.Group className="mb-3">
<Form.Label>Role Akun</Form.Label>
<Form.Select aria-label="pilih user role" value={value.groupid} onChange={onChange}>
<option value="superadmin">Super Admin</option>
<option value="admin">Admin</option>
<option value="admin_rj ">Admin RJ</option>
</Form.Select>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Username</Form.Label>
<Form.Control name="username" value={value.username} onChange={onChange}/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Nama Lengkap</Form.Label>
<Form.Control name="fullname" value={value.fullname} onChange={onChange}/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Email</Form.Label>
<Form.Control type="email" name="email" value={value.email} onChange={onChange}/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Password</Form.Label>
<Form.Control type="password" name="password" value={value.password} onChange={onChange}/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Phone</Form.Label>
<Form.Control type="text" name="phone" value={value.phone} onChange={onChange}/>
</Form.Group>
<Button variant="secondary" type='submit'>
Simpan
</Button>
</Form>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={props.onClose}>
Keluar
</Button>
</Modal.Footer>
</Modal>
);
};
export default ModalCreate;
and action/performing mutation in page call index.js :
import React, { useState } from 'react';
import { useQuery, useMutation } from '#apollo/client';
import { Container, Card, Button, InputGroup, FormControl, Form, Spinner } from 'react-bootstrap';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faSearch } from '#fortawesome/fontawesome-free-solid';
import CardInfo from '../../../component/PengaturanPengguna/CardInfo';
import TableUserInfo from '../../../component/PengaturanPengguna/Table';
import { Loading } from '../../../component/Common';
import ModalCreate from '../../../component/PengaturanPengguna/Modals/ModalCreate';
import { GET_ALL_USERS, GET_USER_BY_ID } from '../../../gql/query';
import { REGISTER_USER } from '../../../gql/mutation';
const SearchInput = () => {
return (
<InputGroup className="mb-3">
<InputGroup.Text>
<FontAwesomeIcon icon={faSearch} />
</InputGroup.Text>
<FormControl
type="text"
placeholder="Search..."
/>
</InputGroup>
)
}
const PengaturanPengguna = (props) => {
// refetch and query data
const { data: usersdata, loading: usersloading, error: userserror } = useQuery(GET_ALL_USERS);
const { refetch, loading } = useQuery(GET_ALL_USERS);
// show modals
const [showModal, setShowModal] = useState(false);
// mutation new register user
const [registerUser, { loading: registerloading, error: registererror }] = useMutation(REGISTER_USER, {
refetchQueries: [{ query: GET_USER_BY_ID }, { query: GET_ALL_USERS }],
onCompleted: data => {
console.log(data)
},
onError: err => {
console.error(err);
}
}) ;
const handleRefreshClick = () => {
refetch();
}
const handleShowModal = () => setShowModal(true);
const handleCloseModal = () => setShowModal(false);
if (usersloading || registerloading) return <Loading/>
if (userserror || registererror) return <p>Error!</p>
return (
<Container>
<CardInfo/>
<Card>
<Card.Title>
<span className='base-md text-regular mt-2 std-txt-primary-200'>Data Pengguna Dashboard</span>
</Card.Title>
<Card.Body>
<div className='d-flex justify-content-between'>
<Form inline>
<SearchInput/>
<Button variant='secondary' onClick={handleRefreshClick} disabled={loading}>{loading ? ( <Spinner
as="span"
animation="border"
size="sm"
role="status"
aria-hidden="true"/> ) : 'Muat Ulang'}</Button>
</Form>
<div>
<Button variant='success' onClick={() => { setShowModal(true) }}>Daftar Akun</Button>
</div>
</div>
<TableUserInfo users={usersdata}/>
</Card.Body>
</Card>
{
showModal ? <ModalCreate show={handleShowModal} onClose={handleCloseModal} action={registerUser} /> : null
}
</Container>
)
}
export default PengaturanPengguna;
and here's my mutation :
const REGISTER_USER = gql`
mutation($input: RegisterInput!) {
register(input: $input) {
username
email
full_name
phone
address
group_id
}
}
`;
Error :
I got this error
Also, Network Status Tabs :
I've been try any solution but it still not working, any help will be appreciated, thank you
If you are getting validation error from apollo for required fields then check the form fields may be name attribute is missing and value is not storing inside your state.

Fields tied to the state doesn't clear on successful form submission

I have a contact form, when the form submission is successful it should clear the form field name, email and message which is tied up to the state. The form submission is successful but form fields name, email and message doesn't clear.
For test purpose what I'm doing is passing default values to the state but this values doesn't get filled in form during initial load.
export default function Contact() {
const [name, setName] = useState('John Doe')
const [email, setEmail] = useState('me#example.com')
const [message, setMessage] = useState('Hello, this is test message.')
const onSubmit = (e) => {
e.preventDefault()
const form = {"name": name, "email": email, "message": message}
return fetch('/api/contact', {
method: 'POST',
body: JSON.stringify(form),
headers: {'Content-Type': 'application/json'}
}).then(response => {
if(response.status === 200){
setName('')
setEmail('')
setMessage('')
} else {
}
}).catch(err => err)
}
return (
<section>
<form method='post'>
<div>
<label>Name</label>
<input type="text" name="name" onChange={(e) => {setName(e.target.value)}}/>
</div>
<div>
<label>Email Address</label>
<input type="email" name="email" onChange={(e) => {setEmail(e.target.value)}}/>
</div>
<div>
<label>Message</label>
<textarea minLength={5} maxLength={2000} rows="6" name="message" onChange={(e) => {setMessage(e.target.value)}}></textarea>
</div>
<div>
<button type='submit' onClick={(e) => {onSubmit(e)}}>Send Message</button>
</div>
</form>
</section>
);
}
As User456 said, you need to add value={variable} for every <input />.
Example:
import { useState } from "react";
export default function Contact() {
const [name, setName] = useState("John Doe");
const [email, setEmail] = useState("me#example.com");
const [message, setMessage] = useState("Hello, this is test message.");
const onSubmit = (e: any) => {
e.preventDefault();
setName("");
setEmail("");
setMessage("");
};
return (
<section>
<form method="post">
<div>
<label>Name</label>
<input
type="text"
name="name"
value={name}
onChange={e => {
setName(e.target.value);
}}
/>
</div>
<div>
<label>Email Address</label>
<input
type="email"
name="email"
value={email}
onChange={e => {
setEmail(e.target.value);
}}
/>
</div>
<div>
<label>Message</label>
<textarea
minLength={5}
maxLength={2000}
name="message"
value={message}
onChange={e => {
setMessage(e.target.value);
}}></textarea>
</div>
<div>
<button
type="submit"
onClick={e => {
onSubmit(e);
}}>
Send Message
</button>
</div>
</form>
</section>
);
}

Clear all fields after submit React js

I have the following code in my react app and I need to have empty input areas after submitting. Please assist me.
import { useRef } from 'react';
import './Contact.css';
import emailjs from 'emailjs-com'
import { useState, useEffect } from 'react';
const Contact = () => {
const formRef = useRef();
const [done, setDone] = useState(false);
const handleSubmit = (e) => {
e.preventDefault();
emailjs.sendForm(
'service_py6v3mm',
'template_db5q8nx',
formRef.current,
'mJDC1if10C25Z-TZC'
)
.then((result) => {
console.log(result.text);
setDone(true);
}, (error) => {
console.log(error.text);
});
}
return (
<div className="c">
<div className='c-wrapper'>
<div className='c-left'>
<h1 className='c-title'> Let's discuss!</h1>
<div className='c-info'>
<div className='c-info-item'>
<div className="c-info-item">
<img
src="./images/Phone.jpg"
alt=""
className="c-icon"
/>
+12345678 </div>
<div className="c-info-item">
<img className='c-icon'
src="./images/Email.png" alt='Email' />
messimacky#gmail.com
</div>
<div className="c-info-item">
<img className='c-icon'
src="./images/Location.jpeg"
alt=" " />
Addis Ababa, Wolo Sefer, Ethio-China Road, Ethiopia
</div>
</div>
</div>
</div>
<div className='c-right'>
<p className='c-desc'> <b> Get in touch!</b>
</p>
<form ref={formRef} onSubmit={handleSubmit}>
<input type='text' placeholder='Name' name='username' />
<input type='text' placeholder='Subject' name='user_subject' />
<input type='text' placeholder='Your email here... ' name='user_email' />
<textarea rows={5} placeholder='message' name='message' /> <br />
<button>Submit</button>
{done && <p> Thank you I will contact you soon!</p>}
</form>
</div>
</div>
</div>
)
}
export default Contact
You can bind every input value to a state and empty them when you submit it. Here I add an example for the username. You can multiply it and use it.
const [username, setUsername] = useState('Name');
const submitFunctionWhichDeletes = () => {
console.log(username);
setUsername('');
}
<input ... value={username} onChange={e => setUsername(e.target.value)} ... />
const compForm = ()=>{
const [formData,addFormData] = useState({
username:"",
subject:"",
email:"",
message:""
})
cosnt formSubmit =()=>{
// make api call
addFormData({
username:"",
subject:"",
email:"",
message:""
})
}
const formData = (e,filed)=>{
const temp = {...formData}
if (filed === "username"){
temp.username = e.target.value
}
else if(filed === "subject"){
temp.subject = e.target.value
}
else if(filed === "email"){
temp.email = e.target.value
}
else if(filed === "message"){
temp.message = e.target.value
}
addFormData(temp)
}
return(
<>
<input type='text' placeholder='Name' name='username'
value={formData.username} onChange={(e)=>formData(e,username)}/>
<input type='text' placeholder='Subject' name='user_subject'
value={formData.subject} onChange={(e)=>formData(e,subject)}/>
<input type='text' placeholder='Your email here... ' name='user_email'
value={formData.email} onChange={(e)=>formData(e,email)}/>
<textarea rows={5} placeholder='message' name='message'
value={formData.message} onChange={(e)=>formData(e,message)}/>
<button onClick = {(e)=>formSubmit()}>Submit</button>
<>
)
}

How to add email validation to below code?

The below code is using cards to show account creation, deposit and other module.
I need to refractor the code to add email, name, and password field validation, but I am not able to do it.
context.js
const Route = ReactRouterDOM.Route;
const Link = ReactRouterDOM.Link;
const HashRouter = ReactRouterDOM.HashRouter;
const UserContext = React.createContext(null);
function Card(props){
function classes(){
const bg = props.bgcolor ? ' bg-' + props.bgcolor : ' ';
const txt = props.txtcolor ? ' text-' + props.txtcolor: ' text-white';
return 'card mb-3 ' + bg + txt;
}
return (
<div className={classes()} style={{maxWidth: "18rem"}}>
<div className="card-header">{props.header}</div>
<div className="card-body">
{props.title && (<h5 className="card-title">{props.title}</h5>)}
{props.text && (<p className="card-text">{props.text}</p>)}
{props.body}
{props.status && (<div id='createStatus'>{props.status}</div>)}
</div>
</div>
);
}
function CardForm(props) {
const ctx = React.useContext(UserContext);
return (
<>
<div style={{maxWidth: "18rem"}}>
<div className="name-field" style={{display: props.showName}}>
Name<br/>
<input type="input"
id="txtName"
className="form-control"
placeholder="Enter name"
onChange={e => ctx.name=e.currentTarget.value} /><br/>
</div>
<div className="email-field" style={{display: props.showEmail}}>
Email address<br/>
<input type="input"
id="txtEmail"
className="form-control"
placeholder="Enter email"
onChange={e => ctx.email=e.currentTarget.value}/><br/>
</div>
<div className="password-field" style={{display: props.showPassword}}>
Password<br/>
<input type="password"
id="txtPassword"
className="form-control"
placeholder="Enter password"
onChange={e => ctx.password=e.currentTarget.value}/><br/>
</div>
<div className="amount-field" style={{display: props.showAmount}}>
Amount<br/>
<input type="number"
className="form-control"
placeholder="Enter amount"
onChange={e => ctx.balance=e.currentTarget.value}/><br/>
</div>
</div>
</>
)
}
creatAccount.js
function CreateAccount(props){
const [show, setShow] = React.useState(true);
const [status, setStatus] = React.useState('');
const ctx = React.useContext(UserContext);
function addUser() {
ctx.balance = '0';
fetch(`/account/find/${ctx.email}`)
.then(response => response.json())
.then(data => {
console.log(data);
if (data.length===0) ctx.user = true;
})
.then(() => {
if (ctx.user===true) {
const url = `/account/create/${ctx.name}/${ctx.email}/${ctx.password}/${ctx.balance}`;
(async () => {
var res = await fetch(url);
var data = await res.json();
console.log(data);
})();
ctx.user='';
setShow(false);
} else {
ctx.user='';
setStatus('User already exists with that email');
setTimeout(() => setStatus(''),3000);
}})
}
return (
<Card
bgcolor="primary"
header="Create Account"
text=""
status={status}
body={
<>
{show ?
<>
<CardForm setShow={setShow} showAmount="none"/>
{<button type="submit" className="btn btn-light" onClick={addUser}>Create Account</button>}
</>
:
<Success setShow={setShow}/>}
</>
}
/>
);
}
function Success(props) {
return (
<>
<h5>Success!</h5><br/>
<button type="submit"
className="btn btn-light"
onClick={() => props.setShow(true)}>Add another account</button>
</>
)
}
I have tried multiple solutions from online content, but they do not solve the problem.
Lets simplify this
Using NPM package email-validator
Install via NPM
npm install email-validator
import * as EmailValidator from 'email-validator';
Bind your local state to your input field e.g
const [email, setEmail] = useState("");
const [valid, setIsValid] = useState(false);
<input
type="text"
name="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
Create a function to check for email validation like below
const validateEmail = (email) => {
setIsValid(EmailValidator.validate(email));
};
Now there comes two cases. One is to show the validation on change the input field or check on submitting the whole form. To give the validation message while inputting email, you have to use the useEffect hook just like below
useEffect(() => {
if (email) {
validateEmail(email);
}
}, [email, validateEmail]);
You can use the valid state for validation message while user is entering the email something like below
<span>{valid ? 'Email format valid' : 'Invalid email format'} <span>
Second Case
just call the function we created above for email validation and check the valid state.

How do I make the invalid hook call go away?

I get this error when trying to npm start my project:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
import React, { useState, useEffect } from 'react';
import './index.css';
import conspireLogo from './conspireLogo.png';
import Post from './Post'
import { auth, db } from './firebase';
import { makeStyles } from '#material-ui/core/styles';
import Modal from '#material-ui/core/Modal';
import { Button, Input } from '#material-ui/core'
import ImageUpload from './imageUpload';
//import { BrowserRouter, Route, Switch } from 'react-router-dom';
function getModalStyle() {
const top = 50;
const left = 50;
return {
top: `${top}%`,
left: `${left}%`,
transform: `translate(-${top}%, -${left}%)`,
};
}
const useStyles = makeStyles((theme) => ({
paper: {
position: 'absolute',
width: 400,
backgroundColor: theme.palette.background.paper,
border: '2px solid #000',
boxShadow: theme.shadows[5],
padding: theme.spacing(2, 4, 3),
},
}));
function MainPage() {
const classes = useStyles();
const [modalStyle] = useState(getModalStyle);
const [posts, setPosts] = useState([]);
const [open, setOpen] = useState(false);
const [openSignIn, setOpenSignIn] = useState(false);
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [email, setEmail] = useState('');
const [user, setUser] = useState(null);
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((authUser) => {
if (authUser) {
console.log(authUser);
setUser(authUser);
} else {
setUser(null);
}
})
return () => {
unsubscribe();
}
}, [user,username]);
useEffect(() => {
db.collection('posts').orderBy('timestamp', 'desc').onSnapshot(snapshot => {
setPosts(snapshot.docs.map(doc => ({
id: doc.id,
post: doc.data()
})));
})
}, []);
const signUp = (event) => {
event.preventDefault();
auth
.createUserWithEmailAndPassword(email, password)
.then((authUser) => {
authUser.user.updateProfile({
displayName: username
})
})
.catch((error) => alert(error.message));
}
const signIn = (event) => {
event.preventDefault();
auth
.signInWithEmailAndPassword(email, password)
.catch((error) => alert(error.message));
setOpenSignIn(false);
}
return (
<div className="app">
<Modal
open={open}
onClose={() => setOpen(false)}
>
<div style={modalStyle} className={classes.paper}>
<form className="app__signup">
<center>
<img
className="app__headerImage"
src={conspireLogo}
alt="Conspire Logo"
/>
</center>
<Input
placeholder="username"
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<Input
placeholder="email"
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<Input
placeholder="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<Button type="submit" onClick={signUp}>Sign Up</Button>
</form>
</div>
</Modal>
<Modal
open={openSignIn}
onClose={() => setOpenSignIn(false)}
>
<div style={modalStyle} className={classes.paper}>
<form className="app__signup">
<center>
<img
className="app__headerImage"
src={conspireLogo}
alt="Conspire Logo"
/>
</center>
<Input
placeholder="email"
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<Input
placeholder="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<Button type="submit" onClick={signIn}>Sign In</Button>
</form>
</div>
</Modal>
<div className="app__header">
<img
className="app__headerImage"
src={conspireLogo}
alt="Conspire Logo"
/>
{user ? (
<Button onClick={() => auth.signOut()}>Logout</Button>
): (
<div className="app__loginContainer">
<Button onClick={() => setOpenSignIn(true)}>Sign In</Button>
<Button onClick={() => setOpen(true)}>Sign Up</Button>
</div>
)}
</div>
<div className="app__footer">
<Button onClick={() => setOpenSignIn(true)}><img
className="app__footerImage"
src="http://www.simpleimageresizer.com/_uploads/photos/bdfbb0d1/346a1f4363e1b59f6860fdce6abc1082_2_15.jpg"
alt="Create"
/>
</Button>
</div>
<div className="app__posts">
<div className="app__postsLeft">
{
posts.map(({id, post}) => (
<Post key={id} postId={id} user={user} username={post.username} caption={post.caption} imageUrl={post.imageUrl}></Post>
))
}
</div>
</div>
{user?.displayName ? (
<ImageUpload username={user.displayName} />
): (
<h3 className="center">Sorry you need to login to upload</h3>
)}
</div>
);
}
export default MainPage;
const [modalStyle] = useState(getModalStyle);
You're storing the function reference, not the function's return. Change it to
const [modalStyle] = useState(getModalStyle());
Moreover as you don't need to change this modalStyle, you don't need to have it in state
<div style={getModalStyle()} className={classes.paper}>
I don't think so there should be any error in this file, please check the other files
ex - Post, ImageUpload

Resources