How select checkbox in Reactjs? - reactjs

I am trying when I click on a checkbox it should get selected and save its value true in localstorage so that if the page is refreshed it should get value from the localstorage, similarly for second checkbox if it is selected too then also save its value true in localstorage.
In simple way if I select a both the checkboxes it should retain even after page refresh this is what I am trying for
Here is my code is what I have tried
Link - https://codesandbox.io/s/musing-architecture-p2nrg?file=/src/App.js:0-1760
import React from "react";
import "./styles.css";
import { Form } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.min.css";
export default function App() {
const data = {
naming: localStorage.getItem("naming") || false,
fullname: localStorage.getItem("fullname") || false
};
const [currentCheckboxId, setCheckboxId] = React.useState(data);
const setCheckbox = event => {
const naming = event.target.checked;
console.log(naming);
localStorage.setItem("naming", naming);
setCheckboxId({
...data,
naming: event.target.checked
});
};
const setCheckbox2 = event => {
const fullname = event.target.checked;
console.log(fullname);
localStorage.setItem("fullname", fullname);
setCheckboxId({
...data,
fullname: event.target.checked
});
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Form>
<>
<Form.Check
onChange={setCheckbox}
type="checkbox"
label="Check me out"
id="first"
checked={currentCheckboxId.naming}
/>
<Form.Group controlId="email">
<Form.Label>Email Address</Form.Label>
<Form.Control type="text" placeholder="Enter email" />
</Form.Group>
</>
<>
<Form.Check
onChange={setCheckbox2}
type="checkbox"
label="Check me out"
id="second"
checked={currentCheckboxId.fullname}
/>
<Form.Group controlId="fullname">
<Form.Label>Name</Form.Label>
<Form.Control type="text" placeholder="Enter name" />
</Form.Group>
</>
</Form>
</div>
);
}

Here is what you need to do:
Initialize the state with false
Use useEffect to run at mounted and retrieve checkbox values from LocalStorage and setState accordingly
Use setState with updater function to set new state which depends on current state
export default function App() {
// 1. Initially "false"
const [currentCheckboxId, setCheckboxId] = React.useState({
naming: false,
fullname: false
});
// 2. useEffect to run # mounted:
// get from LS and update the state
React.useEffect(() => {
const data = {
naming: localStorage.getItem('naming') === 'true' ? true : false,
fullname: localStorage.getItem('fullname') === 'true' ? true : false
};
setCheckboxId(data);
}, []);
const setCheckbox = event => {
const naming = event.target.checked;
console.log('naming', naming);
localStorage.setItem('naming', naming);
// 3. use "function" with prevData as first argument to setState
setCheckboxId(prevData => ({
...prevData,
naming: naming
}));
};
const setCheckbox2 = event => {
const fullname = event.target.checked;
console.log('fullname', fullname);
localStorage.setItem('fullname', fullname);
// 3. same as above
setCheckboxId(prevData => ({
...prevData,
fullname: fullname
}));
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Form>
<>
<Form.Check
onChange={setCheckbox}
type="checkbox"
label="Check me out"
id="first"
checked={currentCheckboxId.naming}
/>
{/* Rest of your code */}
}
Here is a playground.

Related

The Select Dropdown doesn't update back after reload

I created a form where the user inputs data and when the button Save is clicked the data are saved to a database. Everything works fine. You can notice that the country is selected from a memo list and I used a function to save the data rather than a lambda function like the name and the address because I couldn't figure it out. My problem is when I reload the page the country doesn't get back to the form like the name and the address but is stored in the database. The issue is in the code below.
import React, {useState, useEffect , useMemo} from 'react';
import { Button, Row, Col, Form, InputGroup} from 'react-bootstrap';
import obtainFromServer from '../Services/fetchService';
import { useLocalState } from '../util/useLocalStorage';
import countryList from 'react-select-country-list';
import Select from 'react-select';
const TrademarkView = () => {
const [jwt, setJwt] = useLocalState("", "jwt"); //Remove setJwt if we don't use it at the end
const trademarkId = window.location.href.split("/trademarks/")[1];
const [trademark, setTrademark] = useState({
address: "",
country: "",
name: "",
});
//Countries
const [countryinit, setCountryinit] = useState({
value: "",
label: "",
});
const options = useMemo(() => countryList().getData(), []);
const changeHandler = countryinit => {
setCountryinit(countryinit);
console.log(countryinit);
updateTrademark("country",countryinit.label)
}
const styleCountries = {
display: "inline-block",
width: "300px"
};
function updateTrademark(prop, value){
const newTrademark = {...trademark}
newTrademark[prop] = value;
setTrademark(newTrademark);
}
function saveTrademark(){
obtainFromServer(`/api/trademarks/${trademarkId}`, "PUT", jwt, trademark).then(
(trademarkData) =>{
setTrademark(trademarkData);
});
}
useEffect(() => {
obtainFromServer(`/api/trademarks/${trademarkId}`, "GET", jwt)
.then(trademarkData => {
if(trademarkData.address === null) trademarkData.address = "";
if(trademarkData.name === null) trademarkData.name = "";
setTrademark(trademarkData);
});
},[])
return (
<div>
{trademark ? (
<>
<Row>
<Col>
<Form className='m-5'>
<Form.Group controlId="formGridName" className="mb-2">
<Form.Label>Name:</Form.Label>
<Form.Control value={trademark.name} onChange={(e) => updateTrademark("name",e.target.value)}/>
</Form.Group>
<Form.Group className="mb-3" controlId="formGridAddress">
<Form.Label>Address:</Form.Label>
<Form.Control as="textarea" placeholder="1234 Main St" rows={3} value={trademark.address} onChange={(e) => updateTrademark("address",e.target.value)}/>
</Form.Group>
<Form.Group className="mb-3" controlId="formGridCountry">
<Form.Label>Country:</Form.Label>
<div style={styleCountries}><Select options={options} value={countryinit} onChange={changeHandler} /></div>
</Form.Group>
</Form>
</Col>
<Row className='mx-1 px-5'>
<Button onClick={() => saveTrademark()}>Save</Button>
</Row>
</Row>
</>
) : (
<></>
)}
</div>
);
};
export default TrademarkView;
The countryinit has a value(it's the initials of the country) and a label(it's the name of the country). You can see that when I am updating the database I am only sending the label. I have a console.log so you can see the country object.
How can I get the country to be selected after a reload?
I finally figured it out. Changed the select to this and it worked.
<Select options={options} value={options.filter((option) => option.value === trademark.country)} onChange={(e) => updateTrademark("country",e.value)} />
Basically the problem as I mention before is that the country it was an object. And I couldn't send the whole object to the database and I was sending the label which it was wrong. Now I am sending the value to the database and when reading I am redirecting the value from the database to the selected value and setting the label.

I can't catch the value of the checkbox input

I have a React form where I can't control the value of the checkbox input with the useState hook. I don't have this problem with other inputs.
I can't pass the checkbox input value to the AuthData object. When you click the "Sign in" button, the console should display an AuthData object with the fields { login: '', password: '', isRemember: '' }
import React from 'react'
import { useState } from 'react'
export const AuthForm = ({ handlers }) => {
const [authData, setAuthData] = useState({ login: '', password: '', isRemember: '' })
const changeValue = (event) => {
const { id, value } = event.target
setAuthData((prevAuthData) => ({ ...prevAuthData, [id]: value }))
}
const signIn = () => {
console.log(authData)
}
return (
<form onSubmit={(e) => e.preventDefault()}>
<input
type="text"
id="login"
placeholder="Login/E-mail/Phone"
value={authData.login}
onChange={changeValue}
/>
<input
type="password"
id="password"
placeholder="Password"
value={authData.password}
onChange={changeValue}
/>
<input
type="checkbox"
id="isRemember"
value={authData.isRemember}
onChange={changeValue}
/>
<button onClick={signIn}>Sign in</button>
</form>
)
}
When you change inputs values, their values must be passed to the authValue object.
With "login" and "password" inputs their values go into the authValue object, but with "isRemember" input this does not work. The value of checkbox inputs somehow does not get into the authValue object.
you can check the input type and get the checked value for checkbox from the event object as below
const changeValue = (event) => {
let { id, value, type, checked="" } = event.target;
if (type === "checkbox") {
value = checked;
}
setAuthData((prevAuthData) => ({ ...prevAuthData, [id]: value }));
};
You have to use the checked attribute on the checkbox input.
The value attribute is used, but you’ll have to modify it to ensure it sends true or false to the state object
I've added a snippet in response to your comment.
const {useState} = React
const AuthForm = ({ handlers }) => {
const [authData, setAuthData] = useState({ login: '', password: '', isRemember: false })
const changeValue = (event) => {
const { id, value } = event.target
setAuthData((prevAuthData) => ({ ...prevAuthData, [id]: value }))
}
const changeCheckbox = () => {
setAuthData((prevAuthData) => ({ ...prevAuthData, isRemember: !prevAuthData.isRemember }))
}
const signIn = () => {
console.log(authData)
}
console.log(authData);
return (
<form onSubmit={(e) => e.preventDefault()}>
<input
type="text"
id="login"
placeholder="Login/E-mail/Phone"
value={authData.login}
onChange={changeValue}
/>
<input
type="password"
id="password"
placeholder="Password"
value={authData.password}
onChange={changeValue}
/>
<input
type="checkbox"
id="isRemember"
checked={authData.isRemember}
onChange={changeCheckbox}
/>
<button onClick={signIn}>Sign in</button>
</form>
)
}
// Render it
ReactDOM.createRoot(
document.getElementById("root")
).render(
<AuthForm />
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

how to get value in dynamic input to sql React

I'm a newbie react.I had generated input fields dynamically. Now I want to get values firstName and Lastname in this dynamics input fields to the database but I don't know how to get this value.
please help me
his my code App.js
import React, { useState } from "react";
function App() {
const [inputList, setInputList] = useState([{ firstName: "", lastName: "" }]);
const handleInputChange = (e, index) => {
const { name, value } = e.target;
const list = [...inputList];
list[index][name] = value;
setInputList(list);
};
const handleAddClick = () => {
setInputList([...inputList, { firstName: "", lastName: "" }]);
};
return (
<div className="App">
{inputList.map((x, i) => {
return (
<div className="box">
<input
name="firstName"
placeholder="Enter First Name"
value={x.firstName}
onChange={e => handleInputChange(e, i)}
/>
<input
className="ml10"
name="lastName"
placeholder="Enter Last Name"
value={x.lastName}
onChange={e => handleInputChange(e, i)}
/>
<div className="btn-box">
{inputList.length - 1 === i && <button onClick={handleAddClick}>Add</button>}
</div>
</div>
);
})}
<div style={{ marginTop: 20 }}>{JSON.stringify(inputList)}</div>
</div>
);
}
export default App;
Thank you
You need to retrieve values from server side which means you will do fetch process in browser side. Use useEffect to do fetch call and set the response with setInputList.
The below is one way with useEffect. Depending on your pj concept, you can also use useSwr, SSR or etc where data retrieving happens.
import React, { useState, useEffect } from "react";
function App() {
const [inputList, setInputList] = useState([{ firstName: "", lastName: "" }]);
const handleInputChange = (e, index) => {
const { name, value } = e.target;
const list = [...inputList];
list[index][name] = value;
setInputList(list);
};
const handleAddClick = () => {
setInputList([...inputList, { firstName: "", lastName: "" }]);
};
useEffect(()=>{
let canExexute = true;
// Anything to retrieve data such as
// fetch, graphql query,,,etc
// Set values from the above
if (canExecute) setInputList(values)
// Caring about when unmounting component
return ()=>{
canExecute = false;
}
// Don't put inputList state itself as dependancies which causes infinite rendering.
},[dependencies])
return (
<div className="App">
{inputList.map((x, i) => {
return (
<div className="box">
<input
name="firstName"
placeholder="Enter First Name"
value={x.firstName}
onChange={e => handleInputChange(e, i)}
/>
<input
className="ml10"
name="lastName"
placeholder="Enter Last Name"
value={x.lastName}
onChange={e => handleInputChange(e, i)}
/>
<div className="btn-box">
{inputList.length - 1 === i && <button onClick={handleAddClick}>Add</button>}
</div>
</div>
);
})}
<div style={{ marginTop: 20 }}>{JSON.stringify(inputList)}</div>
</div>
);
}
export default App;

Passing values between components in React

I m beginner to reactJS and I m having so much trouble with self learning.
I want to print the data I get from first page.
I used 2 .js files
This is userpage.js:
import resultPage from "./resultPage";
// JS
//const input = document.getElementById('myText');
//const inputValue = input.value
// React
// value, onChange
const Multi = () => {
const [person, setPerson] = useState({ firstName: "", email: "", age: "" });
const [people, setPeople] = useState([]);
const handleChange = (e) => {
const name = e.target.name;
const value = e.target.value;
setPerson({ ...person, [name]: value });
};
const handleSubmit = (e) => {
//e.preventDefault();
if (person.firstName && person.email && person.age) {
const newPerson = { ...person, id: new Date().getTime().toString() };
setPeople([...people, newPerson]);
setPerson({ firstName: "", email: "", age: "" });
resultPage(people, person);
}
};
return (
<>
<article className="form">
<form>
<div className="form-control">
<label htmlFor="firstName">Name : </label>
<input
type="text"
id="firstName"
name="firstName"
value={person.firstName}
onChange={handleChange}
/>
</div>
<div className="form-control">
<label htmlFor="email">Email : </label>
<input
type="email"
id="email"
name="email"
value={person.email}
onChange={handleChange}
/>
</div>
<div className="form-control">
<label htmlFor="age">Age : </label>
<input
type="number"
id="age"
name="age"
value={person.age}
onChange={handleChange}
/>
</div>
<button type="submit" className="btn" onClick={handleSubmit}>
add person
</button>
</form>
</article>
</>
);
};
export default Multi;
This has 2 textboxes and a submit button.
This code is from resultPage.js:
function resultPage(people, person) {
return (
<article>
{people.map((person) => {
const { id, firstName, email, age } = person;
return (
<div key={id} className="item">
<h4>{firstName}</h4>
<p>{email}</p>
<p>{age}</p>
</div>
);
})}
</article>
);
}
export default resultPage;
What am I doing wrong? I m new to reactjs. So kindly spare my obvious mistakes and help me.
From React documentation
HTML form elements work a bit differently from other DOM elements in React, because form elements naturally keep some internal state.
You need to add handleSubmit to your form, and it'll work. As #Halcyon suggested, using a Capital case for a component is good. It's tough to distinguish between HTML elements and components if you use lowercase. Read this for more details.
I am attaching a working sandbox for your code.
You're calling resultPage in handleSubmit. That's not going to work. You want resultPage to be part of the rendering, probably conditionally.
Consider something like:
return <>
{person.firstName !== "" && <resultPage people={people} person={person} />}
{person.firstName === "" && <>
// the form
</>}
</>;
Also since resultPage is a component, it's best to capitalize it.
I think you probably want a 3rd component:
const MyComponent = () => {
const [ people, setPeople ] = React.useState([]);
const [ isEditing, setIsEditing ] = React.useState(false);
return <>
{isEditing && <Multi setPeople={(people) => {
setPeople(people);
setIsEditing(false);
}}
{isEditing === false && <resultPage people={people} />}
</>;
}
Mutli now accepts a prop setPeople that is called in handleSubmit.

React TypeScript: Alternatives to UseRef in functional components

Is there another way of getting/setting the values from the dom that is less expensive than useRef()? Is useRef() to be used lightly as the docs suggest?
import React, { useRef, useEffect } from 'react';
const Join: React.FC = () => {
const fullName = useRef<HTMLInputElement>(null);
const email = useRef<HTMLInputElement>(null);
const password = useRef<HTMLInputElement>(null);
const myForm = useRef<HTMLFormElement>(null);
useEffect(() => {
if (myForm.current) myForm.current.reset();
if (fullName.current) fullName.current.focus();
}, []);
return (
<div>
<form ref={myForm}>
<input type='text' ref={fullName} />
<input type='text' ref={email} />
<input type='text' ref={password} />
</form>
</div>
)
}
When the component loads I want to clear the form and focus the
fullName input
You don't need refs for that
I want to clear the form
Make your inputs controlled
Declare an empty string as initial value
const Component = () =>{
const [state, setState] = useState({
email : '',
password : ''
})
const onChange = ({ target: { value, name } }) =>{
setState(prev => ({
...prev,
[name] : value
}))
}
const { email, password } = state
return(
<>
<input value={email} onChange={onChange} id='email'/>
<input value={password} onChange={onChange} id='password' />
</>
)
}
Automatically focus a given input
Just use autofocus for that
<input autofocus/>

Resources