Show an input field corresponding to radio button selection - reactjs

const next = useRef(false);
const [validate,setValidate] = useState(false);
const [data, setData] = useState(healthform);
return (
<div>
<div class="hQ">
Have you travel anywhere before?
</div>
<div class="hA">
<Radio name={"travAny"} value={data.traAny} onChange={(val,name,isValid)=>{
data[name]=val;
valids[name]=isValid;
}} />
</div>
{(data.traAny && data.traAny !== "0") && <Input placeHolder="If yes, please list all countries: " value={data.traAnyDet} name="traAnyDet" onChange={(val, name, isValid) => {
data[name] = val;
valids[name] = isValid;
}} />}
</div>
);
I want to only display the input field as we select yes on radio button. I tried. But it doesn't show on the time that we pick yes. It only displays when it is already yes.

Looking at your code. I think the problem is with how you update the values. You are directly mutating the state object instaed of updating it using the setState function.
I think changing the way you update the data to a solution like the one below will fix your issue:-
const [data, setData] = useState(healthForm)
<Radio name={"travAny"} value={data.traAny} onChange={(val,name,isValid)=>{
setData(prevData=>({...prevData, [name]:val, }))
}} />
You should do the same for the valids.

Related

How to set radio button 'checked' based on value from database? - React

I have a radio button group in a component. I want to set which radio is selected based on it's value taken from the database in an Update/Edit scenario.
export default function updateRadioSelection(){
const [radioValue, setRadiovalue] = useState("");
useState(()=>{
setRadiovalue("pick"); // <-- Assume this value is taken from database, value may be either "delivery" or "pick"
}, [])
const changeSelection = (e)=>{
setRadiovalue(e.target.value);
}
return(
<div>
<input type="radio" id="delivery" name="orderType" value="delivery" required onChange={changeSelection} />
<label htmlFor="delivery">Delivery</label>
<input type="radio" id="pick" name="orderType" value="pick" onChange={changeSelection} />
<label htmlFor="pick">Pick Up</label>
</div>
)
}
To make a checkbox or radio checked you must use the checked prop for the input element, it receives a boolean value. And you can do something like this
export default function updateRadioSelection(){
const [radioValue, setRadiovalue] = useState("");
// useState will not execute any kind of callback function, for this case you need to use useEffect
useEffect(() => {
const dbResult = getRadioFromDb();
setRadiovalue(dbResult);
}, [])
const changeSelection = (e)=>{
setRadiovalue(e.target.value);
}
return(
<div>
<input type="radio" id="delivery" name="orderType" value="delivery" required onChange={changeSelection} checked={radioValue === 'delivery'} />
<label htmlFor="delivery">Delivery</label>
<input type="radio" id="pick" name="orderType" value="pick" onChange={changeSelection} checked={radioValue === 'pick'} />
<label htmlFor="pick">Pick Up</label>
</div>
)
}
You can read more about radio input in its documentation
Just a few minutes after posting this question I found the answer I was searching for. Turns out it's pretty easy.
Just add checked={radioValue === "pick"} for the Pick Up radio button & the same for other radio button by replacing "pick" with "delivery"
reference - react.tips/radio-buttons-in-reactjs

Trying to add multiple refs to dynamically generated element in ReactJs

I am trying to add multiple refs to a set of dynamically generated checkboxes. At this point, the checkboxes work, but when I am trying to change the checked state of a particular checkbox, it seems the last one is the only one to have the ref and the state updates just for that particular checkbox.
So far I have this:
// Setting 6 as a number of states
new Array(states.length).fill(false)
);
// Adding refs to check values
const inputsRef = useRef([]);
const handleStateChecked = (position) => {
const updateCheckedState = isStateChecked.map((isChecked, index) =>
index === position ? !isChecked : isChecked
);
setStateIsChecked((prevState) => updateCheckedState);
};
return (
{ ... form ...}
{/* Generating state checkboxes dynamically */}
{states.map((state, index) => {
return (
{...div with styles}
<input
type="checkbox"
checked={isStateChecked[index]}
onChange={ () => handleStateChecked(index)}
value={state}
ref={inputsRef}
/>
{state}
</div>
);
})}
</div>
</div>
Could someone guide me in the right direction? Thanks!

useRef is getting cleared when filtering array of objects

I've created one Demo Application where I've been able to add comments while clicking on the chat icon textarea will be expanded, currently, the functionality is I've created a reference using useRef of that particular text area using unique id, and I'm saving comments to that reference array, & rendering on UI using ref.current Method, everything is working as I expected but when I click on those filter buttons, the reference is getting null! my requirement is even though I do filter comments should be persisted!
Any suggestion, Any new Approach except using useRef would be Appreciated! Thanksyou!!
Here's my codesandbox link
https://codesandbox.io/s/proud-resonance-iryir7?file=/src/App.js
Your comment ref should only contains comments, not includes textarea element. So you should create a component to handle textarea value
const TextArea = ({ value, handleSaveComment }) => {
const ref = useRef(null);
return (
<>
<textarea
placeholder="Enter Here"
ref={ref}
defaultValue={value}
></textarea>
<div
className="save-button"
onClick={() => {
handleSaveComment(ref.current.value);
}}
>
Save
</div>
</>
);
};
and use it in table
const handleSaveComment = (fsValidationId, value) => {
comment.current[fsValidationId] = value;
setExpandedId((prev) => (prev === fsValidationId ? "0" : fsValidationId));
};
<AccordionDetails>
<TextArea
handleSaveComment={(value) =>
handleSaveComment(row.id, value)
}
value={comment.current[row.id]}
/>
</AccordionDetails>
You can check full code in my codesandbox. Hope it help!

how can I remove part of data from state in react.js

I create and add some data to my selecetFile2 state / then I want to delete some part of that selecetFile2 state by any event- just guide for function.
const [selectedFile2, setSelectedFile2] = useState([]); //my state for data
const [isFilePicked2, setIsFilePicked2] = useState(false); //just controll for page
this function for control data
const changeHandler2 = (event) => {
setSelectedFile2([...selectedFile2,event.target.files[0]]);
setIsFilePicked(true);}
const multi_img = ()=>{ //It's for input dialog box
document.getElementById("multi_img").click();}
this my main code
<input type="file" onChange={changeHandler2} title="ali ali" id="multi_img"
name="img" accept="image/*" style={{display:'none'}} />
<div><BsFillPlusSquareFill onClick={multi_img} /> //input control by this
{
isFilePicked2 &&
selectedFile2.map(item => <img key={v4()} src={URL.createObjectURL(item)} />)
//this my Item I want to delete for example by click
//I just need function
}
Here you go
<input
type="file"
onChange={changeHandler2}
title="ali ali"
id="multi_img"
name="img"
accept="image/*"
style={{ display: "none" }}
/>
<div>
<BsFillPlusSquareFill onClick={multi_img} /> //input control by this
{
isFilePicked2 &&
selectedFile2.map((item) => (
<img key={v4()} src={URL.createObjectURL(item)} onClick={ () => {
setSelectedFile2(selectedFile2.filter(i => i !== item))
}} />
))
//this my Item I want to delete for example by click
//I just need function
}
</div>
By using useState, you can not directly update or modify the state. Whenever you wanted to modify or update the state you have to do it using the set[nameofstate]. In your case.
whenever you want to update selectedFile2 you have to pass the new value for seletedFile2 to setSelectedFile2(newValueForSelectedFile2).
for more information and examples please visit documenation

How to make react input show state value?

I have title and message variables as the local state in my React component. The idea is that when the component mounts, these two variables get initialised either with the respective values coming from currentPost object which is coming from Redux, or otherwise with an empty string.
const MyComponent = ({ currentPost }) => {
const [title, setTitle] = React.useState(currentPost.title ? currentPost.title : '');
const [message, setMessage] = React.useState(currentPost.message ? currentPost.message : '');
<form>
<div className="form-group">
<input
value={title}
onChange={evt => setTitle(evt.target.value)}
/>
</div>
<div className="form-group">
<input
value={title}
onChange={evt => setTitle(evt.target.value)}
/>
</div>
</form>
const mapStateToProps = state => ({ currentPost: state.posts.currentPost });
};
The code above is actually a modal that opens whenever I click on the edit icon of a given post. In the same time, the currentPost object on Redux state, which is empty, gets populated with the selected post. Then in the above modal component, I get currentPost from Redux state.
The problem is that the two variables always get an empty string, even when currentPost is populated with all the data I need. How can I make the input fields show the right data depending on the currentPost state?
Your logic is correct, there is nothing wrong with it. Just notice that the useState will only be defined when the component renders for the FIRST time. Your redux state is probably being updated only after the component has mounted already.
A quick way of checking that is just to console.log before defining the state.
const MyComponent = ({ currentPost }) => {
// This will probably show "undefined" in the first log
console.log('current Post', currentPost);
const [title, setTitle] = React.useState(currentPost.title ? currentPost.title : '');
const [message, setMessage] = React.useState(currentPost.message ? currentPost.message : '');
<form>
<div className="form-group">
<input
value={title}
onChange={evt => setTitle(evt.target.value)}
/>
</div>
<div className="form-group">
<input
value={title}
onChange={evt => setTitle(evt.target.value)}
/>
</div>
</form>
const mapStateToProps = state => ({ currentPost: state.posts.currentPost });
};
There are two ways of going about it. You can either use the redux state straight into the input and onChange will call a method to update that same state
OR
Use useEffect to update the local state once currentPost changes.
useEffect(() => {
setTitle(currentPost.title);
setMessage(currentPost.message);
}, [currentPost]);
try this:
const [title, setTitle] = React.useState(
currentPost.title && currentPost.title.length ? currentPost.title : ""
);
const [message, setMessage] = React.useState(
currentPost.message && currentPost.message.length ? currentPost.message : ""
);
The currentPost.title condition checks if there is a value in title or it is undefined, if you pass an empty string, then such a condition will return true, in order to check not only for the presence of a value, but also for the presence of some value in it, you can also check the length property, for strings this should work.
You can see the code here:
https://codesandbox.io/s/input-components-o02qg
UPD:
Take a look this example, i make new SandBox, on redux and TS,
https://codesandbox.io/s/serverless-silence-f19lp?file=/src/MyComponent.tsx
P.S. Only I do not understand why create internal state in components, if the state of these components is stored in the Redux store.
P.P.S. Please show more code to understand more

Resources