react page is rendering blank [duplicate] - reactjs

This question already exists:
return not displaying page data react functional component
Closed 1 year ago.
I have this, my entire react page:
import React, { useState, useEffect } from "react";
import axios from "axios";
import { useHistory } from "react-router-dom";
import { useMemo } from "react";
import { connect } from "react-redux";
import AdminNav from "../../../components/admin/AdminNav"
import AdminAboutUsNav from "../../../components/admin/AdminAboutUsNav"
import Header from "../../../components/app/Header";
import { setNavTabValue } from '../../../store/actions/navTab';
import { makeStyles, withStyles } from "#material-ui/core/styles";
import "../../../styles/AddMembershipPage.css";
const AddMembershipPage = (props) => {
const history = useHistory();
const [myData, setMyData] = useState({});
let ssoDetails = {
name: props.blue.preferredFirstName + " " + props.preferredLastName,
email: props.blue.preferredIdentity,
cnum: props.blue.uid,
empType: "part-time"
}
this.state = {
cnum: ssoDetails.cnum,
empType: ssoDetails.empType,
email: ssoDetails.email,
name: ssoDetails.name,
phone: "",
// building: building,
siteList: "",
status: ""
};
const handleInputChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
});
};
const handleSubmit = (e) => {
e.preventDefault();
var date = Date().toLocaleString();
const { cnum, empType, email, name, phone, siteList, status } = this.state;
const selections = {
cnum: cnum,
empType: empType,
email: email,
name: name,
phone: phone,
// building: building,
siteList: siteList,
status: status
};
axios
.post("/newMembership", selections)
.then(
() => console.log("updating", selections),
(window.location = "/admin/services")
)
.catch(function (error) {
// alert(error)
window.location = "/admin/services/new";
});
};
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
backgroundColor: theme.palette.background.paper,
},
}));
const classes = useStyles();
return (
<div className={classes.root}>
<AdminNav />
{/* <Header title="Services - Admin" /> */}
{/* <AdminAboutUsNav /> */}
<div className="App">
<form onSubmit={this.handleSubmit}>
<h1>Join Us!</h1>
<input value={ssoDetails.name} readOnly name="name" onChange={this.handleInputChange}></input>
<input type="email" value={ssoDetails.email} readOnly name="email" onChange={this.handleInputChange}></input>
<input type="hidden" value={ssoDetails.cnum} readOnly name="cnum" onChange={this.handleInputChange}></input>
<input type="text" value={ssoDetails.empType} readOnly name="empType" onChange={this.handleInputChange}></input>
<input type="text" placeholder="Phone Number" name="phone" onChange={this.handleInputChange}></input>
<input type="text" placeholder="Site List" name="siteList" onChange={this.handleInputChange}></input>
{/* <input type="password" placeholder="Password"></input> */}
<button type="submit">Register</button>
</form>
</div>
</div>
);
}
const mapStateToProps = (state) => {
return {
siteTab: state.siteTab,
blue: state.blue
}
}
const mapDispatchToProps = (dispatch, props) => ({
setNavTabValue: (value) => dispatch(setNavTabValue(value))
});
export default connect(mapStateToProps, mapDispatchToProps)(AddMembershipPage);
however, when I try to run this page, it just shows up blank. It started doing this after I added const handleInputChange, and const handleSubmit to the code. I am basically just trying to submit a form, and it is more complex then I imagined. Before I added those 2 things I just mentioned, the page was working perfectly. but now, I cannot figure it out, and really could use some guidance/help to try to fix this up. any ideas?

It's function component so you don't need to call with this.handleSubmit
Just change it to the onSubmit={handleSubmit}> and onChange={handleInputChange}>
Also remove this.state and use useState instead because this.state was available in class based component not in the function component.

Related

i want to prefill form data when update button is clicked.update is working but it does not show the data which one i want to update

I tried using it with the useState hook. singlebook['title'] and singlebook['author'] show right data in the console but not show in form data as prefill data. I am new in the next js.i did it with react and useLocation hook before.but useLocation is not working in next js. if i use value=singlebook['title'] inside the input tag. i can not clicked it and erase that data and can not edit anything
[editBookId].tsx
import React, { useState} from "react";
import { useRouter } from "next/router";
import { useDispatch} from "react-redux";
import { useAppDispatch, useAppSelector } from "../../hooks";
import { getAllBooks, updateBook} from "../../slices/bookSlice";
import { useForm } from "react-hook-form";
import { ToastContainer } from "react-toastify";
const EditBook = () => {
const AllBooks = useAppSelector(getAllBooks);
const {
register,
handleSubmit,
formState: { errors },
} = useForm();
const dispatch = useDispatch();
const router = useRouter();
let editBookId = router.query.editBookId
console.log(editBookId);
//return;
let singlebook='';
AllBooks['books'].map((x)=>{
if(editBookId==x.id){
singlebook=x;
}
}
)
const [data, setData] = useState({
title: singlebook['title'],
author: singlebook['author'],
});
const handleChange = (e) => {
setData({ ...data, [e.target.name]: e.target.value });
};
//const single book = AllBooks['books'];
console.log(singlebook)
const onSubmit = (e) => {
let data={'id':singlebook['id'],...e};
console.log(data)
dispatch(updateBook(data));
router.push("/showBooks");
};
return (
<div>
<ToastContainer/>
<h1 className="text-center">Edit Book</h1>
<div className="d-flex justify-content-center">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="mb-3">
<label htmlFor="text" className="form-label">
Title
</label>
<input
{...register("title", { required: "Title is required" })}
type="text"
name="title"
// value={singlebook['title']}
onChange={handleChange}
className="form-control"
/>
{errors.title?.type === "required" && "Title is required" && (
<p style={{ color: "red" }}>Title is Required.</p>
)}
</div>
<div className="mb-3">
<label htmlFor="text" className="form-label">
Author
</label>
<input
{...register("author", { required: "Author is required" })}
type="text"
name="author"
// value={singlebook['author']}
onChange={handleChange}
className="form-control"
/>
{errors.author?.type === "required" && "Author is required" && (
<p style={{ color: "red" }}>Author is Required.</p>
)}
</div>
<button type="submit" className="btn btn-primary">
Update Book
</button>
</form>
</div>
</div>
);
};
export default EditBook;
every functionality of crud operation is implemented here.all create, read, delete, update is working.
bookSlice.ts
import { PayloadAction } from "#reduxjs/toolkit";
import { toast } from "react-toastify";
const { createSlice } = require("#reduxjs/toolkit");
import { v4 as uuidv4 } from "uuid";
import { RootState } from "../store";
type Book = {
id: string;
title: string;
author: string;
};
type initialState = {
books: Book[];
};
const initialState: initialState = {
books: [
{ id: uuidv4(), title: "new programmer", author: "john smith" },
{ id: uuidv4(), title: "Connecting the dot", author: "john lilly" },
],
};
export const booksSlice = createSlice({
name: "books",
initialState: initialState,
reducers: {
showBooks: (state) => state,
addBook: (state, action: PayloadAction<Book[]>) => {
state.books.push(action.payload);
toast.success("New Book Added");
},
updateBook: (state, action: PayloadAction<Book>) => {
const { id, title, author } = action.payload;
const isBookExist = state.books.filter((book) => book.id === id);
if (isBookExist) {
isBookExist[0].title = title;
isBookExist[0].author = author;
toast.info("Book Updated");
}
},
deleteBook: (state, action: PayloadAction<Book>) => {
const id = action.payload;
state.books = state.books.filter((book) => book.id !== id);
toast.warn("Book Deleted");
},
},
});
export const { showBooks, addBook, deleteBook, updateBook } =
booksSlice.actions;
export const getAllBooks = (state: RootState) => state.books;
export default booksSlice.reducer;

Get method is being called infinitely

I am fetching the data to populate it on the form but when I try to edit the data in the input, the input value will return to its original value and it is because of the get method that is infinitely render on the component. I really need your eyes to see something that have missed or missed up. Thanks in advance y'all.
fetch method
import * as api from '../api/profile';
export const getProfile = () => async (dispatch) => {
try {
const { data } = await api.fetchProfile();
dispatch({ type: 'FETCH_ALL', payload: data });
} catch (error) {
console.log(error.message);
}
}
Profile container
import React, { useState, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getProfile } from '../../../actions/profile'; //fetch method
import Profile from './Profile';
function Index() {
const dispatch = useDispatch();
const posts = useSelector((state) => state.posts);
const currentId = useState(null);
useEffect(() => {
dispatch(getProfile());
}, [currentId, dispatch]);
return (
<div className="custom-container">
{posts.map((profile) => (
<div key={profile._id}>
<Profile profile={profile} currentId={currentId} />
</div>
))}
</div>
);
}
export default Index;
Profile form component
import './Profile.css';
import { React, useState, useEffect } from 'react';
import Button from 'react-bootstrap/Button';
import { TextField } from '#material-ui/core';
import { useDispatch, useSelector } from 'react-redux';
import { updateProfile } from '../../../actions/profile';
const Profile = ({ profile, currentId }) => {
const dispatch = useDispatch();
currentId = profile._id;
const [postData, setPostData] = useState(
{
profile: {
name: "",
description: "",
email: "",
number: "",
}
}
);
const post = useSelector((state) => currentId ? state.posts.find((p) => p._id === currentId) : null);
useEffect(() => {
if(post) setPostData(post);
}, [post])
const handleSubmit = (e) => {
e.preventDefault();
if(currentId) {
dispatch(updateProfile(currentId, postData));
}
}
return (
<form autoComplete="off" noValidate className="form" onSubmit={handleSubmit}>
<TextField
id="name"
name="name"
className="name"
label="Full Name"
variant="outlined"
value={postData.profile.name}
onChange={(e) => setPostData({...postData, profile: {...postData.profile, name: e.target.value}})}
/>
<TextField
id="outlined-multiline-static"
label="Multiline"
multiline
rows={4}
variant="outlined"
size="small"
className="mb-3"
name="description"
value={postData.profile.description}
onChange={(e) => setPostData({...postData, profile: {...postData.profile, description: e.target.value}})}
fullWidth
/>
<TextField
id="email"
label="Email"
variant="outlined"
size="small"
className="mb-3"
name="email"
value={postData.profile.email}
onChange={(e) => setPostData({...postData, profile: {...postData.profile, email: e.target.value}})}
/>
<TextField
id="phone"
label="Phone Number"
variant="outlined"
size="small"
name="phone"
value={postData.profile.number}
onChange={(e) => setPostData({...postData, profile: {...postData.profile, number: e.target.value}})}
/>
<Button variant="light" type="submit" className="Save">Save</Button>
</form>
);
}
export default Profile;
In useEffect you have passed like this , in Profile Container
useEffect(() => {
dispatch(getProfile());
}, [currentId, dispatch]);
in params you have passed dispatch also , so it will call dispatch every time dispatch runs , so it is called infinite times , remove it
It might be because of useEffect.
useEffect(() => {
if(post) setPostData(post);
}, [post])
The post will be a different object each time. check for post property in useEffect dependency like:
useEffect(() => {
if(post) setPostData(post);
}, [post.profile.description])
Also, why are you changing prop value below in Profile component?
currentId = profile._id

How to POST request using axios with React Hooks?

This is my Signupcomponent
const SignupComponent = () => {
const [values, setValues] = useState({
username: 'silvio1',
name: 'Silvioo',
email: 'berlusconi#gmail.com',
password: '123ooo007',
});
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
const { username, name, email, password } = values;
const user = {username, name, email, password};
await axios.post('${API)/signup', user);
};
const handleChange = name => e => {
setValues({ ...values, [name]: e.target.value });
};
const showLoading = () => (loading ? <div className="alert alert-info">Loading...</div> : '');
const signupForm = () => {
return (
<form onSubmit={handleSubmit}>
<div className="form-group">
<input
value={values.username}
onChange={handleChange('username')}
type="text"
className="form-control"
placeholder="Type your username"
/>
</div>
<div className="form-group">
<input
value={values.name}
onChange={handleChange('name')}
type="text"
className="form-control"
placeholder="Type your name"
/>
</div>
<div className="form-group">
<input
value={values.email}
onChange={handleChange('email')}
type="email"
className="form-control"
placeholder="Type your email"
/>
</div>
<div className="form-group">
<input
value={values.password}
onChange={handleChange('password')}
type="password"
className="form-control"
placeholder="Type your password"
/>
</div>
<div>
<button className="btn btn-primary">Signup</button>
</div>
</form>
);
};
return <React.Fragment>
{showLoading()}
{signupForm()}
</React.Fragment>;
};
export default SignupComponent;
EDIT
I changed my code(zhulien's accepted answer).
Signup page appears,I try to sign up user.
I got error
Unhandled Runtime Error
Error: Request failed with status code 404
Call Stack
createError
node_modules/axios/lib/core/createError.js (16:0)
settle
node_modules/axios/lib/core/settle.js (17:0)
XMLHttpRequest.handleLoad
node_modules/axios/lib/adapters/xhr.js (62:0)
Frontend folder
components
config.js
next.config.js
node_modules
package.json
package-lock.json
pages
My pages folder
_document.js
index.js
signin.js
signup.js
signup.js imports the code above
import Link from 'next/link';
import Layout from '../components/Layout';
import SignupComponent from '../components/frontauth/SignupComponent';
const Signup = () => {
return (
<Layout>
<h2>Signup page</h2>
<SignupComponent />
</Layout>
);
};
My next.config.js
{
APP_NAME: 'BLOG FRONTEND',
APP_DEVELOPMENT: 'http://localhost:3000',
PRODUCTION: false
}
And config.js
const { publicRuntimeConfig } = getConfig();
console.log(publicRuntimeConfig);
export const API = publicRuntimeConfig.PRODUCTION
? 'https://cryptoblog.com'
: 'http://localhost:3000';
export const APP_NAME = publicRuntimeConfig.APP_NAME;
I am new to React and React Hooks. How to solve this problem?
First of all, you're trying to access {username}(which doesn't exist) instead of the state property which is values.username. Furthermore, don't use hooks in event handlers, they should be used in the top level body of the component or in custom hooks only. Checkout this: React hooks rules.
So:
In your form you have to use the state(values) properties.
Extract useEffect hook in the main body flow of the component or BETTER remove it altogether as you're not using it properly currently. You're better of with just the simple event handler for form submit which should post the data somewhere without setting any state.
Your code could look something like:
import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { API } from '../../config';
const SignupComponent = () => {
const [values, setValues] = useState({
username: 'silvio1',
name: 'Silvioo',
email: 'berlusconi#gmail.com',
password: '123ooo007',
});
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
const { username, name, email, password } = values;
const user = {username, name, email, password};
await axios.post('${API)/signup', user);
};
const handleChange = name => e => {
setValues({ ...values, [name]: e.target.value });
};
const showLoading = () => (loading ? <div className="alert alert-info">Loading...</div> : '');
const signupForm = () => {
return (
<form onSubmit={handleSubmit}>
<div className="form-group">
<input
value={values.username}
onChange={handleChange('username')}
type="text"
className="form-control"
placeholder="Type your username"
/>
</div>
this is how it should be:
useEffect(() => {
postUser();
}, []);
not inside the function the way you have done it:
const handleSubmit = e => {
e.preventDefault();
setValues({...values});
const { username, name, email, password } = values;
const user = {username, name, email, password};
async function postUser () {
const result = await axios.post('${API)/signup', user);
};
useEffect(() => {
postUser();
}, []);
};
UseEffects aren't meant to be placed inside your functions.Just place them inside your functional component,with some value(or no value) inside your dependency array of the useEffect.These values present inside the array will trigger the useEffect whenever they get changed.

Cannot delete product item from Firebase

I am implementing the Delete function for product item in Firebase by React redux-saga. But I have an issue that the product id to delete has been obtained, but the product has not been removed From Firebase
I do not understand where I am missing
This is my code for product-form
import React, { useState, useEffect } from "react";
import { Form, Container } from "react-bootstrap";
import PropTypes from "prop-types";
import Button from "../../components/Button";
import { CATEGORIES } from "../../constants/categories";
import Loading from "../../components/Loading"
import "../ProductForm/index.css";
const ProductForm = ({
product,
createProductRequest,
fetchProductRequest,
loading,
type }) => {
const [values, setValues] = useState({
image: "",
name: "",
price: 0,
description: "",
categoty: "",
});
const [imageAsFile, setImageAsFile] = useState();
const [isValid, setIsValid] = useState(false);
useEffect(() => {
if (Object.keys(product).length) {
setValues(product);
}
}, [product]);
useEffect(() => {
if (type.CREATE_PRODUCT_SUCCESS) {
fetchProductRequest();
}
}, [fetchProductRequest, type]);
const handleInputChange = (event) => {
// Create new product to update
const newPropdudct = {
...values,
[event.target.name]: event.target.value,
};
// Update new product for value
setValues(newPropdudct);
};
const handleFileChange = (event) => {
const image = event.target.files[0]
setImageAsFile(image)
}
const onHandleSubmit = () => {
if (values.name.trim() === "") {
setIsValid(false);
}
else {
createProductRequest(values, imageAsFile);
}
};
if (loading) {
return (
<Container>
<Loading />
</Container>
);
}
return (
<Container className="product-form">
<Form>
<Form.Group>
<Form.Group>
<Form.File
id="image"
label="Image choose"
value={values.image.name}
onChange={handleFileChange}
/>
</Form.Group>
</Form.Group>
<Form.Group controlId="name">
<Form.Label>Name</Form.Label>
<Form.Control
type="text"
placeholder="Enter product name"
value={values.name}
name="name"
onChange={handleInputChange}
/>
</Form.Group>
<Form.Group controlId="categories">
<Form.Label>Categories</Form.Label>
<Form.Control
as="select"
name="category"
value={values.category}
onChange={handleInputChange}
>
{CATEGORIES.map((category) => (
<option key={category}>{category}</option>
))}
</Form.Control>
</Form.Group>
<Button
btnText="Submit"
size="btn-md"
onClick={onHandleSubmit}
disabled={isValid}
/>
</Form>
</Container>
);
};
export default ProductForm;
This is productAPI which I implement delete from Firebase
import { convertObjectToArray } from "../helpers/product";
import firebaseApp from "./config";
const firebaseDb = firebaseApp.database();
const firebaseStorage = firebaseApp.storage();
/**
* Representation for get list product from firebase
*/
export const onceGetProducts = () =>
firebaseDb
.ref("products")
.once("value")
.then((products) => {
const result = convertObjectToArray(products.val());
return { products: result, status: "ok" };
});
export const deleteProduct = (productId) => {
return firebaseDb.ref('products').child('productId').remove();
}
I already get that Product id, but I cannot delete it from Firebase
I thought I have some missing in productAPI. But I do not know how to resolve it
The button handleDelete function I have imported from another folder. The function implemented by redux-saga.
Anyone have any comment or support for me, I really need your help with this my problem. Thank you so much.
Can you please try the below code
export const deleteProduct = (productId) => {
return firebaseDb.ref('items').child(productId).removeValue();
}

Validation Message is not Showing in SimpleReactValidator library Reactjs

I want to add validation in my react form I am using SimpleReactValidator library for validation, but once I setup the code, the error is not displaying. But when i add
{validator.showMessages('fullName', fullName, 'required|alpha')}
before the return statement it's showing me without click on submit button.
Here's my code
import React, { useState } from 'react';
import SimpleReactValidator from 'simple-react-validator';
const UserDetails = ({ setForm, formData, navigation }) => {
const {
fullName
}= formData;
const useForceUpdate = () => useState()[1];
const validator = new SimpleReactValidator();
const forceUpdate = useForceUpdate();
const submitForm = (e) =>{
e.preventDefault()
if (validator.allValid()) {
alert('You submitted the form and stuff!');
} else {
validator.showMessages();
forceUpdate();
}
}
return(
<>
<input
type="text"
name="fullName"
placeholder='Name'
onChange={setForm}
defaultValue={fullName}
/>
{validator.message('fullName', fullName, 'required|alpha')}
</>
);
}
export default UserDetails;
Hope this will help you
import React, { useState } from 'react';
import SimpleReactValidator from 'simple-react-validator';
const UserDetails = () => {
const validator = new SimpleReactValidator();
const [state, setState] = useState({
fullName:""
})
const handleChnage = (e) => {
setState({
fullName:e.target.value
})
}
const submitForm = () => {
if (validator.allValid()) {
alert('You submitted the form and stuff!');
} else {
validator.showMessages();
}
}
return (
<>
<input
type="text"
name="fullName"
placeholder='Name'
onChange={(e) => handleChnage(e)}
defaultValue={state.fullName}
/>
{validator.message('fullName', state.fullName, 'required|alpha')}
<button onClick={() => submitForm()}>submit</button>
</>
);
}
export default UserDetails;
This code example would solve your problem.
class App extends React.Component {
constructor(props){
super(props)
this.validator = new SimpleReactValidator({autoForceUpdate: this});
this.state = {
fullName: ''
};
}
handleFullNameChange(e) {
this.setState({fullName: e.target.value});
}
handleFullNameBlur() {
if(this.validator.allValid()) {
this.validator.hideMessages();
} else {
this.validator.showMessages();
}
}
render(){
return (
<div>
<input type="text" name="fullName" placeholder='Name' onChange={this.handleFullNameChange.bind(this)} onBlur={this.handleFullNameBlur.bind(this)} value={this.state.fullName} />
{this.validator.message('fullName', this.state.fullName, 'required|alpha')}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'))
You can also take a look on Codepen here: https://codepen.io/aptarmy/pen/oNXRezg

Resources