Page is not showing while using a component for styling - javascript

I am trying to use a container to simplify some styling while learning React and I am having some issues.
Currently this is my Component
import React from 'react'
import { Container, Row, Col } from 'react-bootstrap'
const FormContainer = ({ childern }) => {
return (
<Container>
<Row className="justify-content-md-center">
<Col xs={12} md={6}>
{childern}
</Col>
</Row>
</Container>
)
}
export default FormContainer
And this is where I am loading it into
import React, { useState, useEffect } from 'react'
import { Link } from 'react-router-dom'
import { Form, Button, Row, Col } from 'react-bootstrap'
import { useDispatch, useSelector } from 'react-redux'
import Message from '../components/Message'
import Loader from '../components/Loader'
import FormContainer from '../components/FormContainer'
import { login } from '../actions/userActions'
const LoginScreen = ({location, history}) => {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const dispatch = useDispatch()
const userLogin = useSelector(state => state.userLogin)
const {loading, error, userInfo} = userLogin
const redirect = location.search ? location.search.split('=')[1] : '/' // Takes location of Url, splits after the equals sign, and everything right of it or takes us back to '/'
useEffect(()=> {
if(userInfo) {
history.push(redirect)
}
}, [history, userInfo, redirect])
const submitHandler = (e) => {
e.preventDefault()
dispatch(login(email, password))
}
return (
<FormContainer>
<h1>Sign In</h1>
{error && <Message variant='danger'>{error}</Message>}
{loading && <Loader/>}
<Form onSubmit={submitHandler}>
<Form.Group controlId='email'>
<Form.Label>Email Address</Form.Label>
<Form.Control type='email' placeholder="Enter email" value={email} onChange={(e) => setEmail(e.target.value)}>
</Form.Control>
</Form.Group>
<Form.Group controlId='password'>
<Form.Label>Password</Form.Label>
<Form.Control type='password' placeholder="Enter password" value={password} onChange={(e) => setPassword(e.target.value)}>
</Form.Control>
</Form.Group>
<Button type='submit' variant='primary'>
Sign In
</Button>
</Form>
<Row className='py-3'>
<Col>
New Customer <Link to={redirect ? `/register?redirect=${redirect}` : '/register'}>
Register
</Link>
</Col>
</Row>
</FormContainer>
)
}
export default LoginScreen
When I remove FormContainer and replace it with a div the LoginScreen info shows up but without the styling. Otherwise it is blank with no issues in the Console. My other components seem to to show some stuff, but not the text.
Any help would be amazing.
Thanks!

Related

React web authentication issue with setError and error

I'm making a web authentication app in react based on a YouTube video from Web Dev Simplified (approx 20 min in)and have been running into an odd issue.
I saw someone post a similar question at the same point in development but I don't believe I have the same issue. I'm not getting any errors, the only issue I am having is on the error messages showing. When I submit an email and pair of mismatched passwords it should give me an error message, but I cannot get it to display any errors. This is the code:
./index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './components/App';
import 'bootstrap/dist/css/bootstrap.min.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
./components/App.js
import React from "react";
import Signup from './Signup'
import { Container } from 'react-bootstrap'
import { AuthProvider } from '../contexts/AuthContext'
function App() {
return (
<AuthProvider>
<Container className="d-flex align-items-center justify-content-center" style={{ minHeight: "100vh" }}>
<div className="w-100" style={{ maxWidth: "400px" }}>
<Signup />
</div>
</Container>
</AuthProvider>
)
}
export default App;
./contexts/AuthContext.js
import React, { useContext, useState, useEffect } from 'react'
import { auth } from '../firebase'
const AuthContext = React.createContext()
export function useAuth() {
return useContext(AuthContext)
}
export function AuthProvider({ children }) {
const [currentUser, setCurrentUser] = useState()
function signup(email, password) {
return auth.createUserWithEmailAndPassword(email, password)
}
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(user => {
setCurrentUser(user)
})
return unsubscribe
}, [])
const value = { currentUser, signup }
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
}
./components/Signup.js
import React, { useRef, useState } from 'react';
import { Form, Button, Card, Alert } from 'react-bootstrap';
import { useAuth } from '../contexts/AuthContext';
export default function Signup() {
const emailRef = useRef();
const passwordRef = useRef();
const passwordConfirmRef = useRef();
const { signup } = useAuth();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
async function handleSubmit(e) {
e.preventDefault();
if (passwordRef.current.value !== passwordConfirmRef.current.value) {
return setError("Passwords do not match");
}
try {
setError("");
setLoading(true);
await signup(emailRef.current.value, passwordRef.current.value);
} catch {
setError("Failed to create an account");
}
setLoading(false);
}
return (
<>
<Card>
<Card.Body>
<h2 className="text-center mb-4">Sign Up</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Form.Group id="password">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required />
</Form.Group>
<Form.Group id="password-confirm">
<Form.Label>Password Confirmation</Form.Label>
<Form.Control type="password" ref={passwordConfirmRef} required />
</Form.Group>
</Form>
<Button disabled={loading} className="w-100" type="submit">
Sign Up
</Button>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
Already have an account? Log In
</div>
</>
);
}
I've tried changing the [error, setError] assignment to const [error, setError] = useState(""); and it displayed the initially assigned error properly, but it still refuses to assign any subsequent messages. I've also tried to make sure all the names are correct, and uniform. I have been troubleshooting this for a couple days now to little success. JavaScript is not my main language, and I'm still learning it so I'm sure I'm just missing something simple. Thanks for the help!
I found the issue. I had placed the button outside of the card which caused it to not activate what it was supposed to. Moving the Button tag inside the Card tag fixed everything.

How to use useRef with Material UI

There is something wrong with the code but I didn't found what is it exactly, I guess the question is how to use useRef with Material UI?
I'm trying to code a login page, the code worked fine with original but when I used Material UI's it stopped.
The Code:
import { useContext, useRef } from "react";
import { Context } from "../../context/Context";
import axios from "axios";
import { useState } from "react"
import TextField from '#mui/material/TextField';
import Box from '#mui/material/Box';
import EmailIcon from '#mui/icons-material/Email';
import LockIcon from '#mui/icons-material/Lock';
export default function Login() {
const userRef = useRef();
const passwordRef = useRef();
const { dispatch, isFetching } = useContext(Context);
const [error, setError] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
dispatch({ type: "LOGIN_START" });
try {
const res = await axios.post("/auth/login", {
username: userRef.current.value,
password: passwordRef.current.value,
});
dispatch({ type: "LOGIN_SUCCESS", payload: res.data });
} catch (err) {
dispatch({ type: "LOGIN_FAILURE" });
setError(true)
}
};
return (
<div className="login">
<form className="loginForm" onSubmit={handleSubmit}>
<Box>
<div>
<TextField
type="email"
required
id="outlined-basic"
label="Email"
variant="outlined"
ref={userRef}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<EmailIcon />
</InputAdornment>
),
}}
/>
<TextField
id="outlined-basic"
label="Password"
variant="outlined"
ref={passwordRef}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<LockIcon />
</InputAdornment>
),
}}
/>
</div>
</Box>
</form>
</div>
)
}
I don't know if using ref is correct in Material UI!
The better way to work with MUI TextField is to use a state like this instead of a ref:
const [userEmail, setUserEmail] = useState("")
return <TextField ... value={userEmail} onChange={(e)=>{setUserEmail(e.target.value)}} />
However if you still want to use a useRef instead, maybe the prop inputRef is what you're seeking

Search Box implementation and filter posts?

I've written the code to filter the post in the useEffect. I can't find a way to implement it. I already have 5 posts in my database. I'm bringing all 5 posts using useSelector but I can't find a way to filter while I am typing in the search bar. If I try to set the filtered value in the setListsPosts2(filteredPostList) when fetching those data using the map I didn't get my all posts.
when I do const [listPosts2, setListPosts2] = useState([posts]); it started continues loop and giving error also as asking me add posts in the lists of useEffect dependencies but when i add it it started continues loop of error
here is my homepage.js file
import { useEffect, useState } from 'react';
import { Col, Container, Form, Row } from 'react-bootstrap';
import { ToastContainer } from 'react-toastify';
import { useDispatch, useSelector } from 'react-redux';
import { listPosts } from '../actions/postActions';
import Banner from '../components/Banner';
import Post from '../components/Post';
import Paginate from '../components/Paginate';
const HomePage = ({ match }) => {
const [keyword, setKeyword] = useState('');
const [listPosts2, setListPosts2] = useState([]);
const pageNumber = match.params.pageNumber || 1;
const dispatch = useDispatch();
const postLists = useSelector((state) => state.postLists);
const { posts, pages, page } = postLists;
const postCreate = useSelector((state) => state.postCreate);
const { success: successCreate } = postCreate;
const postUpdate = useSelector((state) => state.postUpdate);
const { success: successUpdate } = postUpdate;
const postDelete = useSelector((state) => state.postDelete);
const { success: deleteSuccess } = postDelete;
useEffect(() => {
const filteredPostList = posts?.filter((post) =>
post.title.toLowerCase().includes(keyword.toLowerCase())
);
setListPosts2(filteredPostList);
dispatch(listPosts(pageNumber));
}, [dispatch, pageNumber, deleteSuccess, successCreate, successUpdate]);
return (
<div>
<ToastContainer />
<Banner />
<div className="my-3">
<Container id="posts">
<Form className="searchBoxForm">
<Form.Control
type="text"
name="q"
onChange={(e) => setKeyword(e.target.value)}
placeholder="Search Posts..."></Form.Control>
</Form>
<h2 className="mt-3" style={{ letterSpacing: '4px' }}>
POSTS
</h2>
<Row className="mt-3">
<Col>
<Row>
{posts
?.map((post) => (
<Col key={post._id} md={3} sm={4}>
<Post post={post} />
</Col>
))
.sort()
.reverse()}
</Row>
<Paginate pages={pages} page={page} />
</Col>
</Row>
</Container>
</div>
</div>
);
};
export default HomePage;

Getting 'Aw snap! : error code: Out of memory'

I was trying to build simple react-redux app using reducers. But every time I open the website it is popping up this error and I couldn't open the console. I tried to clean cookies and caches but no help.
Whenever I change <Posts /> and <Form /> to simple <h1> tags it works perfectly fine, but I can't find the bug.
My code in
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import { reducers } from './reducers/index.js';
import App from './App';
const store = createStore(reducers, compose(applyMiddleware(thunk)));
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'),
);
App.js
import React,{ useEffect, useState } from 'react';
import { Container, AppBar, Typography, Grid, Grow } from '#material-ui/core';
import { useDispatch } from 'react-redux';
import Posts from '../src/components/Posts';
import Form from './components/form';
import { getPosts } from './actions/action';
function App() {
const [currentId, setCurrentId] = useState();
const dispatch = useDispatch();
useEffect(() =>{
dispatch(getPosts());
},[dispatch, currentId]);
return (
<div>
<Container maxWidth='lg'>
<AppBar position='static' color='inherit'>
<Typography variant='h2' align='center' >SimplePRATICE</Typography>
</AppBar>
<Grow in>
<Container>
<Grid container justify='space-between' alignItems='stretch' spacing={3}>
<Grid item xs={12} sm={4}>
<Form currentId={currentId} setCurrentId={setCurrentId} />
</Grid>
</Grid>
</Container>
</Grow>
</Container>
</div>
);
}
export default App;
form.js
import React, { useEffect, useState } from 'react';
import { Paper, Button, TextField, Typography } from '#material-ui/core';
import { useSelector, useDispatch } from 'react-redux';
import { createPost, updatePost } from '../actions/action.js';
function Form({ currentId, setCurrentId }) {
const [postData, setpostData] = useState({ name:'', message:'' });
const post = useSelector((state) => (currentId ? state.posts.find((message) => message._id === currentId ) :null ));
const dispatch = useDispatch();
useEffect(() => {
if (post) setpostData(post);
}, [post]);
const clear = () =>{
setCurrentId(0);
setpostData({ name: '', message:''});
};
const handleSubmit = async (e) => {
e.preventDefault();
if (currentId === 0){
dispatch(createPost(postData));
}else{
dispatch(updatePost(currentId, postData));
}
clear();
};
return (
<Paper>
<Form onSubmit={handleSubmit}>
<Typography>Creating Post</Typography>
<TextField name="name" variant="outlined" label="Name" fullWidth value={postData.name} onChange={(e) => setpostData({ ...postData, name: e.target.value })} />
<TextField name="message" variant="outlined" label="Message" fullWidth multiline rows={4} value={postData.message} onChange={(e) => setpostData({ ...postData, message: e.target.value })} />
<Button varient='contained' color='primary' size='large' type='submit' fullWidth>Submit</Button>
</Form>
</Paper>
)
}
export default Form
Posts.js
import React from 'react';
import Post from './post.js';
import { Grid } from '#material-ui/core';
import { useSelector } from 'react-redux';
function Posts({ setCurrentId }) {
const posts = useSelector((state) => state.posts);
return (
<Grid container alignItems='stretch' spacing={3}>
{posts.map((post) => (
<Grid key={post._id} item xs={12} sm={6} md={6}>
<Post post={post} setCurrentId={setCurrentId} />
</Grid>
))}
</Grid>
)
}
export default Posts
Post.js
import React from 'react';
import { Card, CardActions, CardContent, Button, Typography } from '#material-ui/core/';
import DeleteIcon from '#material-ui/icons/Delete';
import MoreHorizIcon from '#material-ui/icons/MoreHoriz';
import { useDispatch } from 'react-redux';
import { deletePost } from '../actions/action.js';
function Post({ post, setCurrentId }) {
const dispatch = useDispatch();
return (
<Card>
<div>
<Typography varient='h6'>{post.name}</Typography>
</div>
<di>
<Button style={{ color:'white' }} size='small' onClick={()=> setCurrentId(post._id)}><MoreHorizIcon fontSize='default' /></Button>
</di>
<CardContent>
<Typography vaarient='body2' color='textSecondary' component='p'>{post.message}</Typography>
</CardContent>
<CardActions>
<Button size='small' color='primary' onClick={()=> dispatch(deletePost(post._id))} ><DeleteIcon fontSize='small'>Delete</DeleteIcon></Button>
</CardActions>
</Card>
)
}
export default Post
import axios from 'axios';
const url = 'http://localhost:5000/posts';
export const fetchPosts = () => axios.get(url);
export const createPost = (newPost) => axios.post(url, newPost);
export const updatePost = (id, updatedPost) => axios.patch(`${url}/${id}`, updatedPost);
export const deletePost = (id) => axios.delete(`${url}/${id}`);
Your Form component renders itself:
return (
<Paper>
<Form onSubmit={handleSubmit}>
<Typography>Creating Post</Typography>
<TextField name="name" variant="outlined" label="Name" fullWidth value={postData.name} onChange={(e) => setpostData({ ...postData, name: e.target.value })} />
<TextField name="message" variant="outlined" label="Message" fullWidth multiline rows={4} value={postData.message} onChange={(e) => setpostData({ ...postData, message: e.target.value })} />
<Button varient='contained' color='primary' size='large' type='submit' fullWidth>Submit</Button>
</Form>
</Paper>
)
I think you meant <form> which is not a react component.
return (
<Paper>
<form onSubmit={handleSubmit}>
<Typography>Creating Post</Typography>
<TextField name="name" variant="outlined" label="Name" fullWidth value={postData.name} onChange={(e) => setpostData({ ...postData, name: e.target.value })} />
<TextField name="message" variant="outlined" label="Message" fullWidth multiline rows={4} value={postData.message} onChange={(e) => setpostData({ ...postData, message: e.target.value })} />
<Button varient='contained' color='primary' size='large' type='submit' fullWidth>Submit</Button>
</form>
</Paper>
)
You must have selected a wrong element in your html which is not going on well with the code.
Hence please check all the elements properly.
If it is a functional component , check it again.
I had the same issue and it got resolved.

Blank page on state change of Material UI Modal

Hey I have tried a lot of things but I can't seem to get this thing to work I am trying to make a simple modal using material UI but whenever I try to change state it's showing me a blank white page. does anyone have any idea why is it happening here's my code
a
import {Button,Modal} from "#material-ui/core";
import {useState} from "react";
import RegisterBody from '../Register/RegisterForm'
import LoginBody from '../Login/LoginForm'
const UserModel = () => {
const [isOpen, setIsOpen] = useState(false)
const [isLoginModel, setLoginModel] = useState();
const [MainModelBody] = useState(LoginBody);
function handleRegister() {
if (!isLoginModel) {
console.log("Register")
//Todo: Send Register Request
} else {
MainModelBody.setState(RegisterBody)
setLoginModel(false)
}
}
function handleSignIn() {
if (isLoginModel) {
console.log("Login")
//Todo: send Sign in request
} else {
MainModelBody.setState(LoginBody)
setLoginModel(true)
}
}
function handleUserModel() {
setIsOpen(!isOpen)
}
return (
<>
<Button className="userActionButton" onClick={handleUserModel}>Sign In</Button>
<Modal open={isOpen}
onClose={!isOpen}
disablePortal
disableEnforceFocus
disableAutoFocus
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
>
<div className = 'UserModel'>
<LoginBody/>
<Button onClick={handleRegister}>Register</Button>
<Button onClick={handleSignIn}>Sign In</Button>
</div>
</Modal>
</>
);
}
export default UserModel
LoginBody
import {useState} from 'react';
import LoginElements from './LoginElements';
import {FormControl} from "#material-ui/core";
const LoginForm = ()=> {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const handleSubmit = (e) => {
e.preventDefault();
const user = {email, password}
console.log(user)
};
return (
<div className="form">
<FormControl noValidate autoComplete="off" onSubmit={handleSubmit}>
<LoginElements
email={email}
password={password}
setEmail={setEmail}
setPassword={setPassword}
/>
</FormControl>
</div>
);
}
export default LoginForm;
LoginElements
import {Button, TextField} from "#material-ui/core";
const LoginElements = (props) => {
return (
<>
<TextField label="Email" type="email" required value={props.email} onChange={(e) => props.setEmail(e.target.value)}/>
<br/>
<TextField label="Password" type="password" required value={props.password} onChange={(e) => props.setPassword(e.target.value)}/>
<br/>
<Button variant="contained" type="submit">Login</Button>
<Button variant="contained" type="register">Register</Button>
<br/>
<label>{props.email}</label>
<label>{props.password}</label>
</>
)
}
export default LoginElements;
RegisterBody
import {useState} from 'react';
import RegisterElements from './RegisterElements';
const LoginForm = ()=> {
const [email, setEmail] = useState('')
const [confirmEmail, setConfirmEmail] = useState('')
const [password, setPassword] = useState('')
const [confirmPassword, setConfirmPassword] = useState('')
const handleSubmit = (e) => {
e.preventDefault();
const user = {email, password}
console.log(user)
};
return (
<div className="form">
<form noValidate autoComplete="off" onSubmit={handleSubmit}>
<RegisterElements
email={email}
confirmEmail={email}
password={password}
confirmPassword={password}
setEmail={setEmail}
setConfirmEmail={setEmail}
setPassword={setPassword}
setConfirmPassword={setPassword}
/>
</form>
</div>
);
}
export default LoginForm;
Register Elements
import {Button, TextField} from "#material-ui/core";
const RegisterElements = (props) => {
return (
<>
<TextField label="Confirm Email" type="email" required value={props.email}
onChange={(e) => props.setEmail(e.target.value)}/>
<TextField label="Confirm Email" type="email" required value={props.confirmEmail}
onChange={(e) => props.setConfirmEmail(e.target.value)}/>
<br/>
<TextField label="Password"
type="password"
required value={props.password}
onChange={(e) => props.setPassword(e.target.value)}/>
<TextField label="Confirm Password" required value={props.confirmPassword}
onChange={(e) => props.setConfirmPassword(e.target.value)}/>
<br/>
<Button variant="contained" type="Login">Login</Button>
<Button variant="contained" type="submit">Login</Button>
<label>{props.email}</label>
<label>{props.password}</label>
</>
)
}
export default RegisterElements;
My apologies for bad code i am new with react
You are "toggling" the isLoginModel state but you only render LoginBody in the JSX.
You should be able to use the isLoginModel state and conditionally render either the LoginBody or RegisterBody component into the modal body. There's really no need for the extra state to hold a component reference.
import {Button,Modal} from "#material-ui/core";
import {useState} from "react";
import RegisterBody from '../Register/RegisterForm'
import LoginBody from '../Login/LoginForm'
const UserModel = () => {
const [isOpen, setIsOpen] = useState(false)
const [isLoginModel, setLoginModel] = useState(true); // login by default
function handleRegister() {
if (!isLoginModel) {
console.log("Register");
// TODO: Send Register Request
} else {
setLoginModel(false);
}
}
function handleSignIn() {
if (isLoginModel) {
console.log("Login");
// TODO: send Sign in request
} else {
setLoginModel(true);
}
}
function handleUserModel() {
setIsOpen(isOpen => !isOpen);
}
return (
<>
<Button className="userActionButton" onClick={handleUserModel}>Sign In</Button>
<Modal open={isOpen}
onClose={!isOpen}
disablePortal
disableEnforceFocus
disableAutoFocus
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
>
<div className='UserModel'>
{isLoginModel ? <LoginBody /> : <RegisterBody />} // <-- condition render
<Button onClick={handleRegister}>Register</Button>
<Button onClick={handleSignIn}>Sign In</Button>
</div>
</Modal>
</>
);
}

Categories