React multiple modal in one web page with different buttons - javascript

The advanced Search modal and the add modal are not opening at all. I am learning react for the first time so please help. Thanking you in advance.
App.js:
import React,{ useState } from 'react'
import Logo from './components/Logo.js'
import './App.css'
import PredictBtn from './components/PredictBtn.js'
import Analytics from './components/AnalyticsView.js'
import Advsrchmodal from './components/Advsrchmodal.js'
import Search from './components/Search.js'
import Add from './components/Addmodal.js'
export default function App(){
const [showAdd, setShowAdd] = useState(false);
const [showAdvanced, setShowAdvanced] = useState(false);
return(
<div>
<body>
<Logo />
<div className='header-btns'>
<PredictBtn/><Analytics/>
<button onClick={()=> setShowAdvanced(true)} className="leftbtns adv-srch-btn"id="adv-srch-modal">ADVANCED SEARCH</button>
<Advsrchmodal onClose={()=> setShowAdvanced(false)} show={showAdvanced}/>
<Search />
<button onClick={()=> setShowAdd(true)} className="rightbtns add-btn" id ="add-modal">ADD</button>
<Add onClose={()=> setShowAdd(false)} show={showAdd}/>
</div>
</body>
</div>
)
}
Add Modal.js:
import React from 'react'
const Addmodal= props => {
if(!props.showAdd){
return null
}
return (
<div className='modal overlay' id= 'add-modal '>
<div className="modal-content" id= 'add-modal '>
<div className="modal-header" id= 'add-modal '>
<h4 className="modal-title" id= 'add-modal '>Add</h4>
</div>
< div className="modal-body" id= 'add-modal '>
<input type="text" placeholder='Document ID' id='doc_id' className="modal-input" />
<input type="text" placeholder='Invoice Id' id='invoice_id' className="modal-input" />
<input type="text" placeholder='Customer Number' id='cust_number' className="modal-input" />
<input type="text" placeholder='Business Year' id='business_year' className="modal-input" />
<input type="text" placeholder='Document ID' id='doc_id' className="modal-input" />
<input type="text" placeholder='Invoice Id' id='invoice_id' className="modal-input" />
<input type="text" placeholder='Customer Number' id='cust_number' className="modal-input" />
<input type="text" placeholder='Business Year' id='business_year' className="modal-input" />
</div>
<div className="modal-footer" id= 'add-modal '>
<button className="addbtn " id= 'add-modal '>ADD</button>
<button className="cancel" id= 'add-modal ' onClick={props.onClose}>CANCEL</button>
</div>
</div>
</div>
)
}
export default Addmodal
Advsrchmodal.js:
import React from 'react'
const Advsrchmodal = props=> {
if(!props.showAdvanced){
return null
}
return (
<div className='modal overlay' id="adv-srch-modal" >
<div className="modal-content"id="adv-srch-modal">
<div className="modal-header"id="adv-srch-modal">
<h4 className="modal-title"id="adv-srch-modal"> Advance Search</h4>
</div>
< div className="modal-body"id="adv-srch-modal">
<input type="text" placeholder='Document ID' id='doc_id' className="modal-input" />
<input type="text" placeholder='Invoice Id' id='invoice_id' className="modal-input" />
<input type="text" placeholder='Customer Number' id='cust_number' className="modal-input" />
<input type="text" placeholder='Business Year' id='business_year' className="modal-input" />
</div>
<div className="modal-footer"id="adv-srch-modal">
<button className="advsrchbtn"id="adv-srch-modal">SEARCH</button>
<button className="cancel"id="adv-srch-modal" onClick={props.onClose}>CANCEL</button>
</div>
</div>
</div>
)
}
export default Advsrchmodal
The advanced Search modal and the add modal are not opening at all. I am learning react for the first time so please help. Thanking you in advance.

You are passing the props as show so you have to access it with its name
if(!props.show){
return null
}
try this in both modal components

You should remove most of the code and try to understand what is happening. Go with piece by piece. Your basic idea seems to be okay, but it is lacking some knowledge on the react side. What I would do is that the parent view is responsible for showing the modal and not the component itself. Just look at my simple example which I created https://codesandbox.io/s/cold-shape-wqv1by?file=/src/ModalEample.jsx
use state for toggling if the modal is open or not. Use the main view for deciding if the modal should be seen or not. Then pass the toggle to the modal component. Use destructuring for getting the props. I suppose most of the stuff are new for you, but to understand what is happening and why you should first remove some code and go with piece by piece. Remove the other modal and start working with only one modal.

Related

When ever I submit my form I get the form data in my URL instead of it posting to my backend

I am having an issue when I submit my form it puts all of the form data into my URL instead of sending it to my backend. I'm not sure what the issue is at first I thought it was because I didn't have a method="post" in the form tag but that didn't fix my issue because it tried to send the form data to localhost:3000/register instead of localhost:5000/register. Any help would be appreciated.
Bellow is my current Frontend code.
import { BrowserRouter as Router, Route, Routes, Link } from 'react-router-dom'
import '../css/register.css';
import {IoMdArrowRoundBack} from 'react-icons/io'
import { useState } from 'react'
import axios, { Axios } from 'axios';
const Register = () => {
const [emailReg, setEmailReg] = useState("");
const [usernameReg, setUsernameReg] = useState("");
const [passwordReg, setPasswordReg] = useState("");
const register = () => {
Axios.post('http://localhost:5000/register', {
email: emailReg,
username: usernameReg,
password: passwordReg,
}).catch(function (error) {
console.log(error);
});
};
return (
<div className='background-image'>
<div className='back-button'>
<Link to='/'>
<IoMdArrowRoundBack id='back-arrow' />
<h3>Home</h3>
</Link>
</div>
<div className="container-wrapper">
<div className="container">
<h1>Create Account</h1>
<div className="wrapper">
<form>
<div className="textarea" id="email">
<input
type="email"
onChange={(e) => {
setEmailReg(e.target.value);
}}
name="email"
id="authentactor-email"
placeholder="Email"
defaultValue=""
required
/>
</div>
<div className="textarea" id="username">
<input
type="text"
onChange={(e) => {
setUsernameReg(e.target.value);
}}
name="name"
id="authentactor-text"
placeholder="Username"
defaultValue=""
required
/>
</div>
<div className="textarea" id="password">
<input
type="password"
onChange={(e) => {
setPasswordReg(e.target.value);
}}
name="password"
id="authentactor-password"
placeholder="Password"
defaultValue=""
required
/>
</div>
<div id="button-wrapper">
<button id="button" onClick={register}>Create Account</button>
</div>
</form>
<div className='bottom-text-wrapper'>
<h4>Already have an account? <Link to='/login'>Login Here</Link></h4>
</div>
</div>
</div>
</div>
</div>
)
}
export default Register
According to HTML Living Standard
The missing value default and invalid value default are the Submit Button state.
You can find more information on this question but basically adding type="button" to your Create Account button should do the job.
(so something like <button id="button" type="button" onClick={register}>Create Account</button>)
I figured it out for some reason I can't have the "name" tag in my input fields like it is below.
<div className="textarea" id="password">
<input
type="password"
onChange={(e) => {
setPasswordReg(e.target.value);
}}
name="password"
id="authentactor-password"
placeholder="Password"
defaultValue=""
required
/>
</div>
<div id="button-wrapper">
<button onClick={register} id="button">Create Account</button>
</div>
As soon as I removed the "name" tags I was able to POST my form to the backend and I only get a question mark in my url now instead of all the form data. To fix the question mark I had to set button type="button".
correct code below.
<div className="textarea" id="password">
<input
type="password"
onChange={(e) => {
setPasswordReg(e.target.value);
}}
id="authentactor-password"
placeholder="Password"
defaultValue=""
required
/>
</div>
<div id="button-wrapper">
<button type="button" onClick={register} id="button">Create Account</button>
</div>

An object literal cannot have multiple properties with the same name in strict mode React Typescript

I have this modal window component. The problem is that when I want to submit some of the modal window props, an error occurs because of the line below:
<form className="modal-content-sizes-form" onSubmit={(e)=>{cartStore.handleSubmitForm(e,{**pizzaStore**.modalProps.name, **pizzaStore**.modalProps.description, **pizzaStore**.size, **pizzaStore**.price, **pizzaStore**.modalProps.ImageUrl})}}>
So the question is, what is wrong with writing pizzaStore.modalProps.name? Because this doesn't let the app compile
Here is the full code of the component:
import React from 'react'
import pizzaStore from './stores/PizzaStore'
import {observer} from "mobx-react-lite"
import cartStore from './stores/CartStore';
import { action } from 'mobx';
function ModalWindowComponent({activeModal, setActiveModal}:any){
const [selectedOption, setSelectedOption]=React.useState("small")
const handleSetOption=(e:any)=>{
setSelectedOption(e.target.value);
pizzaStore.setSize(selectedOption);
pizzaStore.setPrice(selectedOption)
}
return (
<div className={activeModal?"modal active":"modal"} onClick={()=>{setActiveModal(false); setSelectedOption("small")}}>
<div className="modal-content" onClick={(e)=>{e.stopPropagation()}}>
<div className="modal-content-header">
<button onClick={()=>setActiveModal(false)}>Close</button>
</div>
<img src={pizzaStore.modalProps.modalImageUrl} className="modal-content-img"/>
<p className="modal-content-pizza-name">{pizzaStore.modalProps.name}</p>
<p className="modal-content-pizza-desc">{pizzaStore.modalProps.description}</p>
<p className="modal-content-pizza-size">{pizzaStore.size}см</p>
<p className="modal-content-pizza-weight">{pizzaStore.setWeight(selectedOption)}грамм</p>
<p className="modal-content-pizza-price">{pizzaStore.price}Руб.</p>
<form className="modal-content-sizes-form" onSubmit={(e:any)=>{cartStore.handleSubmitForm(e,{pizzaStore.modalProps.name, pizzaStore.modalProps.description, pizzaStore.size, pizzaStore.price, pizzaStore.modalProps.ImageUrl})}}>
<label>
<input name="radio-size"value="small" type="radio" onChange={handleSetOption} checked={!activeModal||selectedOption==="small"} className="modal-content-sizes-form-option"/>Маленькая</label>
<label>
<input name="radio-size"value="medium" type="radio" onChange={handleSetOption}checked={selectedOption==="medium"}className="modal-content-sizes-form-option"/>Средняя</label>
<label>
<input name="radio-size"value="big" type="radio" onChange={handleSetOption}checked={selectedOption==="big"} className="modal-content-sizes-form-option"/>Большая</label>
<button onClick={()=>{setActiveModal(false);console.log(cartStore.cartItems, pizzaStore.price)}}>Добавить</button>
</form>
</div>
</div>
)
}
export default observer(ModalWindowComponent)

React setState hook keeps resetting and rendering the page twice

I have an react app Form component split into Login and Signup forms. It is supposed to render the Signup by default but switch to Login if login is button is clicked. When login button is clicked, the page switches to the Login form very briefly before switching back to the Signup form. I don't know what is causing this. I have tried placing const [page, setPage] = setState("signup") in the parent App and passing setPage as a prop along with page. This produced the same results. I believe this issue is similar to this one but that was not resolved.
Here is the app:
import Form from "./components/Signup-Form.js";
function App() {
return (
<div className="App">
<h1>Welcome</h1>
<Form />
</div>
);
}
export default App;
and Signup-Form.js:
import React from "react";
import { useState, useEffect } from "react";
import "./Forms.css";
import { InputField, Buttons } from "./Inputs";
function Form() {
const [page, setPage] = useState("signup");
const pageLabel = page;
let Signup = () => {
function toLogin() {
setPage("login");
}
return (
<form action="" method="get" className="form">
<div className="input-container">
<InputField name="Company Name" id="comp-name" type="text" />
<InputField name="Company ID" id="comp-id" type="text" />
<InputField name="Username" id="username" type="text" />
<InputField name="Email" id="email" type="email" />
<InputField name="Password" id="password" type="password" />
<InputField name="Confirm Password" id="confirm-password" type="password" />
</div>
<div className="btns">
<Buttons name="Sign Up" id="signup-btn" type="submit" cls="success" />
<Buttons name="Log In" id="login-btn" type="button" cls="success" alt="true" onClick={toLogin} />
</div>
</form>
);
};
let Login = () => {
function toSignup() {
setPage("signup");
}
return (
<form action="" method="get" className="form">
<div className="input-container">
<InputField name="Company ID" id="comp-id" type="text" />
<InputField name="Password" id="password" type="password" />
</div>
<div className="btns">
<Buttons name="Log In" id="login-btn" type="submit" cls="success" />
<Buttons name="Sign Up" id="signup-btn" type="submit" cls="success" alt onClick={toSignup} />
</div>
</form>
);
};
let form = (formType) => (
<div className="outer-wrapper">
<div className="form-wrapper">
<label className="form-title">{pageLabel}</label>
{formType}
</div>
</div>
);
if (page === "signup") {
const signup = Signup();
return form(signup);
} else if (page === "login") {
const login = Login();
return form(login);
}
}
export default Form;
The reason why after you click on Login button and get Login page and the page immediately re-renders and you get the Signup page is conditional render in your example. Right after clicking on Login button your state still previous and for this reason after click you get the main (Signup) page.
Suggest to change the structure render into smth like this:
...
return (
<div className="outer-wrapper">
<div className="form-wrapper">
<label className="form-title">{pageLabel}</label>
{page === "signup" && Signup()}
{page === "login" && Login()}
</div>
</div>
);
Here is the example in an action - https://codesandbox.io/s/smoosh-water-6jj18?file=/src/App.js

Why is my checkbox not displaying in reactjs?

I am trying to display a checkbox when the add button is clicked but it refuses to display. Take a look at the addTask() function and you will see what I am trying to do. Thank you, in advance!
import React, { Component } from 'react';
import './App.css';
import './Login.jsx';
import './Navbar.jsx';
class MainPage extends Component {
render() {
return (
<div>
<div className="main-container">
<h1 style={{textDecoration:'underline'}}>Tasks</h1>
<div className="input-group mb-3">
<input type="text" id="task" className="form-control" placeholder="New Task"/>
<div className="input-group-append">
<button id="btn" className="btn btn-success" onClick={this.addTask()}>Add</button>
</div>
</div>
</div>
</div>
);
}
addTask() {
var tasks = document.getElementById('task');
localStorage.setItem('user-task', tasks);
return(
<input type="checkbox" label={localStorage.getItem('user-task')} />
)
}
}
export default MainPage;

Calling a function inside render function - ReactJS?

Ok so I am making a "buzzfeed" quiz generator and I am having an issue with a piece of my form. So for each question made there are two different parts, a "Question" and the "Answers". There will always be 4 answers but I want to keep track of which Answers are checked later so I would like to give each answer a unique id "question" + questionNum + "Answer" + answerNum or "question" + questionNum + "Answer" + i So I made this answersGenerator function that is supposed to give me 4 unique answer choice fill ins for the user to input answers for that specific questions (right now it says something about terms and conditions - ignore that I ad just left it like that for now because I was following a tutorial). Here is all my code:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import logo from './logo.svg';
import './App.css';
var questionNum = 1;
var answerNum = 1;
class App extends Component {
constructor(props) {
super(props);
this.state = {
quizTitle: "",
author: "",
question: "",
terms: false,
test: "",
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSubmit(event) {
event.preventDefault();
console.log(this.state);
}
render() {
return (
<div className="App">
<div>
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
<div className="container">
<div className="columns">
<div className="formDiv">
<form className="form" onSubmit={this.handleSubmit}>
<div className="field">
<label className="label">Give your quiz a title.</label>
<div className="control">
<input
className="input"
type="text"
name="quizTitle"
value={this.state.quizTitle}
onChange={this.handleChange}
/>
</div>
</div>
<div className="field">
<label className="label">Who's the Author?</label>
<div className="control">
<input
className="input"
type="text"
name="author"
value={this.state.author}
onChange={this.handleChange}
/>
</div>
</div>
<div className="questions" id="questions">
<div className="question" id={'questionGroup' + questionNum}>
<div className="field">
<label className="label" id={'question' + questionNum}>Question {questionNum}</label>
<div className="control">
<input
className="input"
type="text"
name='question'
value={this.state.question}
onChange={this.handleChange}
/>
</div>
</div>
<div className="answersDiv">
<label className="label">Answers</label>
<div className="field">
<div className="control">
<label className="checkbox">
{this.answersGenerator()}
</label>
</div>
</div>
</div>
</div>
</div>
<div className="field">
<div className="endButtons">
<button id="addQuestionButton"
onClick={addQuestion}>Add Question</button>
<input
type="submit"
value="Submit"
id="submitButton"
className="button is-primary"
/>
</div>
</div>
</form>
</div>
<div className="column is-3">
<pre>
<code>
<p>Quiz Title: {this.state.quizTitle}</p>
<p>Author: {this.state.author}</p>
<p>Question: {this.state.question}</p>
<p>Terms and Condition: {this.state.terms}</p>
<p>Do you test?: {this.state.test}</p>
</code>
</pre>
</div>
</div>
</div>
</div>
);
}
}
function answersGenerator () {
console.log("hello this is answer generator");
var div = document.createElement('div');
div.className = 'answers' + {questionNum};
for (var i = 1; i < 5; i++){
div.innerHTML =
'<div className="field">\
<div className="control">\
<label className="checkbox">\
<label className="label">Answers</label>\
<input\
name="terms"\
type="checkbox"\
id="question'+{questionNum}+'Answer'+{i}+'"\
checked={this.state.terms}\
onChange={this.handleChange}\
/>\
I agree to the{" "}\
terms and conditions\
</label>\
</div>';
document.getElementsByClassName('answersDiv')[0].appendChild(div)
}
}
function addQuestion () {
questionNum++;
console.log(questionNum + "that is the question number");
var div = document.createElement('div');
div.className = "questions" + questionNum;
div.innerHTML =
'<div id="questionGroup'+{questionNum}+'">\
Question '+{questionNum}+'<br />\
<input type="text" name="question'+{questionNum}+'"/><br />\
Answers<br />\
Check the box(es) for the correct answer(s).<br />\
<input type="checkbox" name="question'+{questionNum}+'Answer1Box" />\
<label for="question'+{questionNum}+'Answer1"><input type="text" name="question'+{questionNum}+'Answer1"/></label><br />\
<input type="checkbox" name="question'+{questionNum}+'Answer2Box" id= />\
<label for="question'+{questionNum}+'Answer2"><input type="text" name="question'+{questionNum}+'Answer2"/></label><br />\
<input type="checkbox" name="question'+{questionNum}+'Answer3Box" />\
<label for="question'+{questionNum}+'Answer3"><input type="text" name="question'+{questionNum}+'Answer3"/></label><br />\
<input type="checkbox" name="question'+{questionNum}+'Answer4Box" />\
<label for="question'+{questionNum}+'Answer4"><input type="text" name="question'+{questionNum}+'Answer4"/></label><br />\
</div>';
document.getElementsByClassName('questions')[0].appendChild(div)
}
export default App;
There's a few things to just ignore in here, i just wasn't sure how much info you needed. So the issue is that I get an error when I call my answersGenerator function in my render function. Here's the error Uncaught TypeError: this.answersGenerator is not a function Here's the small piece where that is
<div className="answersDiv">
<label className="label">Answers</label>
<div className="field">
<div className="control">
<label className="checkbox">
{this.answersGenerator()}
</label>
</div>
</div>
</div>
I appreciate the help, if you have any other tips for me other than this issue I am having I am all ears. I am very new at this, being js and React.
UPDATE: I have edited the answersDiv to be just this (I relized it was being called inside a checkbox)
<div className="answersDiv">
<label className="label">Answers</label>
{answersGenerator()}
</div>
I am still getting the same errors though.
You're receiving the error because the answersGenerator() isn't a method of your class App, so, you can't refer to it using this. If you want to do on that way, move you function to inside the component, like this:
class App extends Component {
// your component definition etc..
answersGenerator = () => {
// your function implementation
}
// the rest of your component
}
TIP:
If you dont want to have to always bind the function, like:
this.handleChange = this.handleChange.bind(this);
Declare your method like:
handleChange = (event) => { // the implementation }
Instead of
handleChange(event) { // the implementation }
The () => {}, known as arrow function, does the bind for your.
EDIT
You're developing with React, that supports creating HTML inside your code. So, you can create an array of answers, then, return a div with the answers mapped inside. The map will take each answer and render inside the div. Try to define your method as below:
answersGenerator => () {
console.log("hello this is answer generator");
var answers = []
for (var i = 1; i < 5; i++){
answers.push(
<div className="field">
<div className="control">
<label className="checkbox">
<label className="label">Answers</label>
<input
name="terms"
type="checkbox"
id=`question${questionNum}Answer${i}`
checked={this.state.terms}
onChange={this.handleChange}
/>
I agree to the{" "}
terms and conditions
</label>
</div>
);
}
return <div className=`answer${questionNum}`> {answers.map(answer => answer)} </div>
}
At first glance it looks like you haven't defined your answersGenerator() function within your App class.
Thus, this.answersGenerator() doesn't exist.
Try just using answersGenerator() without the this.

Categories