I am making a simple calculator app with react in which I want to display the value of the button component in the Display component, but I'm not getting how to do this
Here are the Codes :
Code Of Calculator Component:
import React from "react";
import "./Calculator.css";
import Button from "./Button";
import { useState } from "react";
import Display from "./Display";
const Calculator = () => {
const [Data, setData] = useState("");
return (
<>
<center>
<h1 className="title">Calculator</h1>
<br />
<Display data={Data} />
<div className="btncontainer">
<Button name="+" onClick={() => setData("+")}></Button>
<Button name="-" onClick={() => setData("-")}></Button>
<Button name="/" onClick={() => setData("/")}></Button>
<Button name="X" onClick={() => setData("X")}></Button>
<Button name="1" onClick={() => setData("1")}></Button>
<Button name="2" onClick={() => setData("2")}></Button>
<Button name="3" onClick={() => setData("3")}></Button>
<Button name="4" onClick={() => setData("4")}></Button>
<Button name="5" onClick={() => setData("5")}></Button>
<Button name="6" onClick={() => setData("6")}></Button>
<Button name="7" onClick={() => setData("7")}></Button>
<Button name="8" onClick={() => setData("8")}></Button>
<Button name="9" onClick={() => setData("9")}></Button>
<Button name="0" onClick={() => setData("0")}></Button>
<Button name="=" onClick={() => setData("=")}></Button>
</div>
</center>
</>
);
};
export default Calculator;
Code Of Display Component:
import React from "react";
const Display = (props) => {
console.log("Props in display : ", props);
const handleOnChange = (e) => {
props.data = e.target.value;
};
return (
<input type="text" value={props.data} onChange={handleOnChange} readOnly />
);
};
export default Display;
Code Of Button Component:
import React from "react";
import "./Button.css";
const Button = (props) => {
return (
<input
type="button"
className="btn"
value={props.name}
onClick={props.onClick(props.name)}
></input>
);
};
export default Button;
As I've just started learning React, please ignore my silly mistakes
In the Button component, if you want to pass an argument to the function, you want to set the onClick to an arrow function.
onClick={()=>props.onClick(props.name)}
In the Display component, you should pass in the setData function and use that for the onChange.
onChange={(e)=>setData(e.target.value)}
If you want a string of all the buttons clicked, you can change the button onClick to add to the current value of data instead of replacing it.
For example, for button 5:
onClick={()=>setData(data+'5'}
Related
Consider the code below:
function Item({name, _key})
{
console.log('rendering Item')
const [updatingName, setUpdatingName] = useState(false);
const nameInputElement = useRef();
useEffect(() => {
if (updatingName) {
nameInputElement.current.focus();
}
}, [updatingName]);
function onUpdateClick() {
setUpdatingName(true);
}
function onCancelClick() {
setUpdatingName(false);
}
return (
<div>
<input ref={nameInputElement} type="text" defaultValue={name} name="name"
disabled={!updatingName} />
{!updatingName
? <>
<button key={1} type="button" onClick={onUpdateClick}>Update</button>
<button key={2} type="submit" name="delete" value={_key}>Remove</button>
</>
: <>
<button key={3} type="submit" name="update" onClick={(e) => {setUpdatingName(false)}}>Save</button>
<button key={4} type="button" onClick={onCancelClick}>Cancel</button>
</>}
</div>
)
}
function ItemList({title})
{
return <>
<h1>{title}</h1>
<form method="post" onSubmit={(e) => {console.log('submitting');e.preventDefault()}}>
<Item name={'small'} _key={0} />
</form>
</>
}
export default ItemList;
The problem that I am facing is the click of the Save button. When it's clicked, as you can see, I trigger a state change. But at the same time, I also want the button to cause the underlying <form>'s submission.
(To check whether the form is submitted, I've prevented its default submit mechanism and instead gone with a simple log.)
However, it seems to be the case that when the state change is performed from within the onClick handler of the Save button, it ceases to submit the form. If I remove the state change from within the handler, it then does submit the form.
Why is this happening?
Live CodeSandbox demo
When you call setUpdatingName(false) in save button's click handler, the button is removed from the DOM before submitting. You can add the logic for showing the buttons in ItemList, like below:
function ItemList({ title }) {
const [updatingName, setUpdatingName] = useState(false);
return (
<>
<h1>{title}</h1>
<form
method="post"
onSubmit={(e) => {
e.preventDefault();
setUpdatingName(false);
console.log("submitting");
}}
>
<Item
name={"small"}
_key={0}
updatingName={updatingName}
setUpdatingName={setUpdatingName}
/>
</form>
</>
);
}
export default ItemList;
function Item({ name, _key, updatingName, setUpdatingName }) {
console.log("rendering Item");
const nameInputElement = useRef();
useEffect(() => {
if (updatingName) {
nameInputElement.current.focus();
}
}, [updatingName]);
function onUpdateClick() {
setUpdatingName(true);
}
function onCancelClick() {
setUpdatingName(false);
}
return (
<div>
<input
ref={nameInputElement}
type="text"
defaultValue={name}
name="name"
disabled={!updatingName}
/>
{!updatingName ? (
<>
<button key={1} type="button" onClick={onUpdateClick}>
Update
</button>
<button key={2} type="submit" name="delete" value={_key}>
Remove
</button>
</>
) : (
<>
<button key={3} type="submit" name="update">
Save
</button>
<button key={4} type="button" onClick={onCancelClick}>
Cancel
</button>
</>
)}
</div>
);
}
Also, you could use useTransition to ask React to delay the state update, so the submission happens first:
function Item({ name, _key }) {
console.log("rendering Item");
const [isPending, startTransition] = useTransition();
const [updatingName, setUpdatingName] = useState(false);
const nameInputElement = useRef();
useEffect(() => {
if (updatingName) {
nameInputElement.current.focus();
}
}, [updatingName]);
function onUpdateClick() {
setUpdatingName(true);
}
function onCancelClick() {
setUpdatingName(false);
}
return (
<div>
<input
ref={nameInputElement}
type="text"
defaultValue={name}
name="name"
disabled={!updatingName}
/>
{!updatingName ? (
<>
<button key={1} type="button" onClick={onUpdateClick}>
Update
</button>
<button key={2} type="submit" name="delete" value={_key}>
Remove
</button>
</>
) : (
<>
<button
key={3}
type="submit"
name="update"
onClick={(e) => {
startTransition(() => setUpdatingName(false));
}}
>
Save
</button>
<button key={4} type="button" onClick={onCancelClick}>
Cancel
</button>
</>
)}
</div>
);
}
I made a form project with react. My form is working well for now but I want add bootstrap modal to my form.
When I click the enter button, I want to show a modal. I found modal example on the web but I can't establish connection between form and modal. This is my form
import React from "react";
import { useState } from "react";
const Contact = () => {
const [showModal, setShowModal] = useState(false);
const [inputValue, setInputValue] = useState("");
const [emailValue, setEmailValue] = useState("");
const [phoneNumberValue, setPhoneValue] = useState("");
const [countryValue, setCountryValue] = useState("");
const buttonOnClick = () => {
if (inputValue === "" || emailValue === "" || phoneNumberValue === "") {
setShowModal(false)
} else {
setShowModal(true)
setInputValue("")
}
console.log(`Form submitted, ${showModal}`);
}
return (
<div className="main">
<form >
<div className="baslik">
<div className="container center">
<h1>Contact Form</h1>
</div>
</div>
<div className="field" >
<label className="text"> Name And Surname: </label>
<input type="text" className="form" placeholder="Kerem Kurt" required value={inputValue} onChange={(e) => setInputValue(e.target.value)} />
</div>
<div className="field">
<label className="text"> E-mail: </label>
<input type="email" className="form" placeholder="udenditfy#gmail.com" required value={emailValue} onChange={(e) => setEmailValue(e.target.value)} />
</div>
<div className="field">
<label className="text"> Phone Number: </label>
<input type="tel" className="form" pattern="[0-9]*" placeholder="+905373199437" required value={phoneNumberValue} onChange={(e) => setPhoneValue(e.target.value)} />
</div>
<div className="field">
<label className="text" required > Country: </label>
<select className="form" placeholder="Turkiye" required value={countryValue} onChange={(e) => setCountryValue(e.target.value)}>
<option value="Turkiye">Turkiye</option>
<option value="Azerbaijan">Azerbaijan</option>
<option value="Japan">Japan</option>
<option value="Serbia">Serbia</option>
<option value="France">France</option>
</select>
</div>
<button type="button" className="button" onClick={() => buttonOnClick()}> Enter </button>
</form>
</div>
);
};
export default Contact;
And this is modal codes;
import React, { useState } from 'react';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
function Example() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
<Button variant="primary" onClick={handleShow}>
Launch static backdrop modal
</Button>
<Modal
show={show}
onHide={handleClose}
backdrop="static"
keyboard={false}
>
<Modal.Header closeButton>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>
I will not close if you click outside me. Don't even try to press
escape key.
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary">Understood</Button>
</Modal.Footer>
</Modal>
</>
);
}
render(<Example />);
If you want to open your modal after the event "click" in your Form component, you have to import the modal in your form.
For example, your Form is in a component called "Form.jsx" and Modal is in "Modal.jsx" :
Inside Form.jsx, you must import your Modal, move the "show" state into your Form.jsx and pass it in Modal props, just like that :
import Modal from '/path/to/Modal.jsx'
const [show, setShow] = useState(false);
<form>
{children}
</form>
<Modal show={show} setShow={setShow}/>
Inside your Modal.jsx, just change a few things :
function Modal(props){
// remove the show State
// Remove the Button with "handleShow" function.
const handleClose = () => props.setShow(false);
<Modal show={props.show}>
<Button onClick={handleClose}>Close</Button>
</Modal>
}
Welcome to world of react development!
Your question is a classic question about sharing state between components. This is what you refer to as "connection" between components.
The solution is generally referred to as "lifting state up". I highly recommend reading through that if you haven't already.
Example:
import React from 'react';
import ReactDOM from 'react-dom/client';
import { useState } from "react";
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
const root = ReactDOM.createRoot(document.getElementById('root'));
const Contact = ({toggleShow}) => {
return (
<div className="main">
<form >
<button type="button" className="button" onClick={() => toggleShow()}> Show Modal </button>
</form>
</div>
);
};
const MyModal = ({show, toggleShow}) => {
return (
<>
<Modal
show={show}
onHide={toggleShow}
backdrop="static"
keyboard={false}
>
<Button variant="secondary" onClick={toggleShow}>
Close
</Button>
</Modal>
</>
);
}
const App = () => {
const [show, setShow] = useState(false);
const toggleShow = () => setShow(!show);
return (
<>
<Contact toggleShow={toggleShow}/>
<MyModal show={show} toggleShow={toggleShow}/>
</>
)
}
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Explanation:
The general idea is to share the show state of the Modal as well as the state toggler toggleShow() between our <Contact> and <MyModal> components.
We can easily achieve this:
create a new parent component <App> (the name is arbitrary) where we define the show state and the toggler function.
pass the state and toggler into the modal: <MyModal state={state} toggleShow={toggleShow} />.
the form only needs the toggler: <Form toggleShow={toggleShow} />
Note that toggleShow can also be split into separate handleShow and handleClose function, but this approach saves us a few lines.
return (
{jobstate.jobs.map((data,i) =>{
<form>
<input type="text" placeholder="Post a comment" onChange={(e) => jobcmthandler(e,data._id,i) } />
<button type="button" onClick={postcmt} >Send</button>
</form>
})}
)
I generate dynamic HTML using the map function and I want to disabled button if text null for induvial form and also how to get text value on button click in react js
I can't really see why you'd want to do this but here you go (example):
import React, { useState } from "react";
export default function App() {
return ["Name", "Age"].map((label) => <Form label={label} />);
}
function Form({ label }) {
const [readValue, writeValue] = useState("");
return (
<form>
<label>{label}</label>
<input
type="text"
placeholder="Post a comment"
onChange={(e) => writeValue(e.target.value)}
value={readValue}
/>
<button
type="button"
onClick={() => console.log("Submit")}
disabled={readValue === ""}
>
Send
</button>
</form>
);
}
Am a bit new to react and redux. I am trying to call/show another stateless component's div from parent component. For example, if I have the below code
const funcA = ({key}) = > {
return (
<div>
<input type="checkbox">
</div>
);
};
export default funcA
const funcB = ({key}) = > {
return (
<React.Fragment>
<div>
<input type="text" placeholder="age" />
</div>
<div id="showThisDiv">
<input type="text" placeholder="age" />
</div>
</React.Fragment>
);
};
export default funcB
I am not trying go with classes. In Stateless components I know how to show/hide a section by using the useState, but I can only do this while in the same component. The issue or rather the challenge, is when I try to show/hide a section from another component. How would I show/hide the div with id showThisDiv in funcB when the checkbox is toggled in funcA?
It's possible using redux, but you also can do it using state and react hooks:
check out this codesandbox: https://codesandbox.io/s/vibrant-driscoll-odqmo
App.js
import React from "react";
import "./styles.css";
import FuncA from "./FuncA";
import FuncB from "./FuncB";
export default function App() {
const [age, setAge] = React.useState(0);
handleInput = (event) => {
console.log(event.target.value);
setAge(age === 0 ? 1 : 0);
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<FuncA age={age} onChange={handleInput} />
<FuncB age={age} />
</div>
);
}
FuncA.js
import React from "react";
export default function FuncA(props) {
return (
<>
<label htmlFor="checkbox">
<input type="checkbox" name="age" onChange={props.onChange} value={props.age} />
</label>
</>
);
}
FuncB.js
import React from "react";
export default function FuncB(props) {
return (
<>
{props.age === 0 && <div className="divA">show div a</div>}
{props.age === 1 && <div className="divB">show div b</div>}
</>
);
}
Yeah, is something like this:
EDIT:
// ComponentA.js
const ComponentA = props => <input type="checkbox" onChange={props.onChange} />
// ComponentB.js
const ComponentB = props => (
<>
<div>
<input type="text" placeholder="age" />
</div>
{props.visible && (
<div id="showThisDiv">
<input type="text" placeholder="age" />
</div>
)}
</>
)
// App.js
const App = () => {
const [visible, setVisible] = useState(false);
return (
<>
<ComponentA onChange={() => setVisible(!visible)} />
<ComponentB visible={visible} />
</>
)
}
Now as you want..
I have a FieldArray in Redux Form that I push objects inside this array and right after that I have a callback to trigger a function to make a POST request.
When I submit the form I get the old values, because the push() method of the Redux Form is an async dispach from redux.
// Parent component
<FieldArray
name="myObjects"
component={ChildComponent}
onSubmitObjects={this.onSubmit} />
// Function
onSubmit = async () => {
const { getFormValues } = this.props;
const data = {
myObjects: getFormValues.myObjects
}
try {
// const contact = await Service.updateUser(data);
} catch (e) {
console.log(e)
}
}
I need to submit the form with the new values added in the array right after the push method.
// Function inside ChildComponent
addNewObject = () => {
const { fields, onSubmitObjects} = this.props;
fields.push({
number: 1,
name: 'Foo',
});
if (onSubmitObjects) {
onSubmitObjects(); // cb() to trigger a function in the parent component
}
}
Is there a way to call the callback with the new values right after the push method?
You should use a form with redux-form handleSubmit to wrap your FieldArray. You can optionally pass your custom submit function (to make API requests, submit validation, etc.) to handleSubmit so it'd look like this <form onSubmit={handleSubmit(this.onSubmit)}> ...
See this example from redux-form official docs:
FieldArraysForm.js
import React from 'react'
import {Field, FieldArray, reduxForm} from 'redux-form'
import validate from './validate'
const renderField = ({input, label, type, meta: {touched, error}}) => (
<div>
<label>{label}</label>
<div>
<input {...input} type={type} placeholder={label} />
{touched && error && <span>{error}</span>}
</div>
</div>
)
const renderHobbies = ({fields, meta: {error}}) => (
<ul>
<li>
<button type="button" onClick={() => fields.push()}>Add Hobby</button>
</li>
{fields.map((hobby, index) => (
<li key={index}>
<button
type="button"
title="Remove Hobby"
onClick={() => fields.remove(index)}
/>
<Field
name={hobby}
type="text"
component={renderField}
label={`Hobby #${index + 1}`}
/>
</li>
))}
{error && <li className="error">{error}</li>}
</ul>
)
const renderMembers = ({fields, meta: {error, submitFailed}}) => (
<ul>
<li>
<button type="button" onClick={() => fields.push({})}>Add Member</button>
{submitFailed && error && <span>{error}</span>}
</li>
{fields.map((member, index) => (
<li key={index}>
<button
type="button"
title="Remove Member"
onClick={() => fields.remove(index)}
/>
<h4>Member #{index + 1}</h4>
<Field
name={`${member}.firstName`}
type="text"
component={renderField}
label="First Name"
/>
<Field
name={`${member}.lastName`}
type="text"
component={renderField}
label="Last Name"
/>
<FieldArray name={`${member}.hobbies`} component={renderHobbies} />
</li>
))}
</ul>
)
const FieldArraysForm = props => {
const {handleSubmit, pristine, reset, submitting} = props
return (
<form onSubmit={handleSubmit}>
<Field
name="clubName"
type="text"
component={renderField}
label="Club Name"
/>
<FieldArray name="members" component={renderMembers} />
<div>
<button type="submit" disabled={submitting}>Submit</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</div>
</form>
)
}
export default reduxForm({
form: 'fieldArrays', // a unique identifier for this form
})(FieldArraysForm)