React Buttons and State - how to avoid too many States? - reactjs

I am still somewhat of a novice to React with much to learn. At the moment I am trying to make a page displaying lightsabers and hilts from Star Wars by clicking a button to show the ones you want. I am doing this by using State, which by the amount of states I currently have seems like the wrong way of doing it.
Here's how I'm doing it: I set a State and put an onClick event that sets the chosen hilt/color to true and the rest to false whilst also rendering information of said hilt/color. It looks like this:
import { ReactComponent as QuiGon } from './qui-gon.svg';
import { ReactComponent as ObiWan } from './obi-wan.svg';
import { ReactComponent as ObiWanOld } from './obi-hilt-old.svg';
import { ReactComponent as DarthMaul } from './darth-maul-hilt.svg';
import { ReactComponent as AhsokaHilt } from './ahsoka-hilt.svg';
import { ReactComponent as AnakinHilt } from './anakin-hilt.svg';
import { ReactComponent as VaderHilt } from './darth-vader-hilt.svg';
import { ReactComponent as KyloHilt } from './kylo-ren-hilt.svg';
import './App.css';
function App() {
const [nonChosen, setNonChosen] = useState(true);
const [blue, setBlue] = useState(false);
const [red, setRed] = useState(false);
const [green, setGreen] = useState(false);
const [purple, setPurple] = useState(false);
const [yellow, setYellow] = useState(false);
const [white, setWhite] = useState(false);
const [saberOne, setSaberOne] = useState(true);
const [doubleSaber, setDoubleSaber] = useState(false);
const [quiGon, setQuiGon] = useState(false);
const [obiWanNew, setObiWanNew] = useState(false);
const [obiWanOld, setObiWanOld] = useState(false);
const [ahsoka, setAhsoka] = useState(false);
const [anakinHilt, setAnakinHilt] = useState(false);
const [vaderHilt, setVaderHilt] = useState(false);
const [kyloHilt, setKyloHilt] = useState(false);
return (
<div className="App">
{/* Colors */}
<button className="testsub" onClick={() => {setGreen(true); setWhite(false); setYellow(false); setPurple(false); setRed(false); setBlue(false); setNonChosen(false);}}>Green
</button>
<button className="testsub" onClick={() => {setBlue(true); setWhite(false); setYellow(false); setPurple(false); setRed(false); setGreen(false); setNonChosen(false);}}>Blue
</button>
<button className="testsub" onClick={() => {setRed(true); setWhite(false); setYellow(false); setPurple(false); setBlue(false); setGreen(false); setNonChosen(false);}}>Red
</button>
<button className="testsub" onClick={() => {setPurple(true); setWhite(false); setYellow(false); setGreen(false); setRed(false); setBlue(false); setNonChosen(false);}}>Purple
</button>
<button className="testsub" onClick={() => {setYellow(true); setWhite(false); setPurple(false); setGreen(false); setRed(false); setBlue(false); setNonChosen(false);}}>Yellow
</button>
<button className="testsub" onClick={() => {setWhite(true); setYellow(false); setPurple(false); setGreen(false); setRed(false); setBlue(false); setNonChosen(false);}}>White
</button>
<br />
{/* Hilts */}
<button className="testsub" onClick={() => {setDoubleSaber(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false); setObiWanOld(false);}}>Darth Maul
</button>
<button className="testsub" onClick={() => {setQuiGon(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setDoubleSaber(false); setSaberOne(false); setObiWanNew(false); setObiWanOld(false);}}>Qui Gon
</button>
<button className="testsub" onClick={() => {setObiWanNew(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanOld(false);}}>Obi Wan
</button>
<button className="testsub" onClick={() => {setObiWanOld(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Obi Wan Old
</button>
<button className="testsub" onClick={() => {setAhsoka(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setObiWanOld(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Ahsoka Tano
</button>
<button className="testsub" onClick={() => {setAnakinHilt(true); setKyloHilt(false); setVaderHilt(false); setAhsoka(false); setObiWanOld(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Anakin
</button>
<button className="testsub" onClick={() => {setVaderHilt(true); setKyloHilt(false); setAnakinHilt(false); setAhsoka(false); setObiWanOld(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Vader
</button>
<button className="testsub" onClick={() => { setKyloHilt(true);setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setObiWanOld(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Kylo
</button>
<div class="lightsaber">
<input type="checkbox" id="on-off" />
{nonChosen && (
<>
<div className="blade colol"></div>
{/* <div className="blade2 colol"></div> */}
</>
)}
{blue && (
<div className="blade colol2"></div>
)}
{red && (
<div className="blade red-clr"></div>
)}
{green && (
<div className="blade colol"></div>
)}
{purple && (
<div className="blade purple-clr"></div>
)}
{yellow && (
<div className="blade yellow-clr"></div>
)}
{white && (
<div className="blade white-clr"></div>
)}
{saberOne && (
<label className="hilt" for="on-off">
<QuiGon />
</label>
)}
{doubleSaber && (
<>
<div className="blade2 colol"></div>
<label className="hilt" for="on-off">
<DarthMaul />
</label>
</>
)}
{quiGon && (
<label className="hilt" for="on-off">
<QuiGon />
</label>
)}
{obiWanNew && (
<label className="hilt" for="on-off">
<ObiWan />
</label>
)}
{obiWanOld && (
<label className="hilt" for="on-off">
<ObiWanOld />
</label>
)}
{ahsoka && (
<label className="hilt" for="on-off">
<AhsokaHilt />
</label>
)}
{anakinHilt && (
<label className="hilt" for="on-off">
<AnakinHilt />
</label>
)}
{vaderHilt && (
<label className="hilt" for="on-off">
<VaderHilt />
</label>
)}
{kyloHilt && (
// <label className="hilt" for="on-off">
// <KyloHilt className="hilt2"/>
// </label>
<>
<div className="blade3 colol"></div>
<div className="blade4 colol"></div>
<label className="hilt" for="on-off">
<KyloHilt className="hilt2"/>
</label>
</>
)}
</div>
<div className="infobox">
{nonChosen && (
<div>Yoyoyo</div>
)}
{blue && (
<div>aasdsd</div>
)}
{green && (
<div>fgfgfg</div>
)}
</div>
</div>
);
}
export default App;
It is not completed hence a bit messy, but the problem shows quite nice. I have a lot of States and the buttons gets quite long with all the setX(false).
Is there any way to do this in a better way? I've been pondering for a long time about doing it pure CSS, with if/else etc. but I can't seem to wrap my head around how go get the button to display one thing and leave the rest hidden without having to over-specify it like I already am. Again I am still a novice, so any help would really be appreciated (and again sorry for the spaghetti code)!

You can initialize the values in an object and use them as initial state
const initialValues = {
nonChosen: true,
blue: false,
red: false,
green: false,
purple: false,
yellow: false,
white: false,
// All other states in this or create a seperate object with seperate useState according to your wish
};
And initialize the state as
const [colors, setColors] = useState(initialValues);
Setting the value during onClick as
<button className="testsub" onClick={() => {setColors({...colors,green:true,white:false,yellow:false,purple:false,red:false,blue:false,nonchosen:false})>Green</button>
During rendering:
{colors.nonChosen && (
<>
<div className="blade colol"></div>
{/* <div className="blade2 colol"></div> */}
</>
)}

You can use useReducer hook.
Also, you can inline event (for color) or callback event (for hilt).
I used two cases.
const initialColorState = {
nonChosen: false,
blue: false,
red: false,
green: false,
purple: false,
yellow: false,
white: false,
};
const initialHiltState = {
saberOne: false,
doubleSaber: false,
quiGon: false,
obiWanNew: false,
obiWanOld: false,
ahsoka: false,
anakinHilt: false,
vaderHilt: false,
kyloHilt: false
}
function colorReducer(state, action) {
switch (action.type) {
case "Blue": {
return {
...state,
...initialColorState,
blue: true,
}
}
case "Red": {
return {
...state,
...initialColorState,
red: true,
}
}
case "Green": {
return {
...state,
...initialColorState,
green: true,
}
}
case "Purple": {
return {
...state,
...initialColorState,
purple: true,
}
}
case "Yellow": {
return {
...state,
...initialColorState,
yellow: true,
}
}
case "White": {
return {
...state,
...initialColorState,
white: true,
}
}
}
}
function hiltReducer(state, action) {
switch (action.type) {
case "DoubleSaber": {
return {
...state,
...initialHiltState,
doubleSaber: true,
}
}
case "QuiGon": {
return {
...state,
...initialHiltState,
quiGon: true,
}
}
case "ObiWanNew": {
return {
...state,
...initialHiltState,
obiWanNew: true,
}
}
case "ObiWanOld": {
return {
...state,
...initialHiltState,
obiWanOld: true,
}
}
case "Ahsoka": {
return {
...state,
...initialHiltState,
ahsoka: true,
}
}
case "Anakin": {
return {
...state,
...initialHiltState,
anakinHilt: true,
}
}
case "Vader": {
return {
...state,
...initialHiltState,
vaderHilt: true,
}
}
case "Kylo": {
return {
...state,
...initialHiltState,
kyloHilt: true,
}
}
}
}
function App() {
const [colorState, colorDispatch] = useReducer(colorReducer, initialColorState)
const [hiltState, hiltDispatch] = useReducer(hiltReducer, initialHiltState);
const onHiltClick = useCallback((event) => {
hiltDispatch({type: event.value});
}, [hiltDispatch]);
return (
<div className="App">
{/* Colors */}
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Green" })
}}
>
Green
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Blue" })
}}
>
Blue
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Red" })
}}
>
Red
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Purple" })
}}
>
Purple
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Yellow" })
}}
>
Yellow
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "White" })
}}
>
White
</button>
<br />
{/* Hilts */}
<button className="testsub" onClick={onHiltClick} value="DoubleSaber">
Darth Maul
</button>
<button className="testsub" onClick={onHiltClick} value="QuiGon">
Qui Gon
</button>
<button className="testsub" onClick={onHiltClick} value="ObiWanNew">
Obi Wan
</button>
<button className="testsub" onClick={onHiltClick} value="ObiWanOld">
Obi Wan Old
</button>
<button className="testsub" onClick={onHiltClick} value="Ahsoka">
Ahsoka Tano
</button>
<button className="testsub" onClick={onHiltClick} value="Anakin">
Anakin
</button>
<button className="testsub" onClick={onHiltClick} value="Vader">
Vader
</button>
<button className="testsub" onClick={onHiltClick} value="Kylo">
Kylo
</button>
.....
)
}
export default App;

Related

Submit and close modal window. React React-Hook-Form Typescript

I want to submit and close with the button "save". change type to "button" type="submit" value="submit" onClick={ onClose } don't submit and don't close. I am using onClose for close the modal
import { useAppDispatch } from '../redux/hooks';
import { userInfo } from '../redux/model';
import { useForm } from 'react-hook-form';
import { ModalProps } from '../redux/model';
import { setList } from '../redux/slice';
type UI = userInfo;
const AddData: React.FC<ModalProps> = ({ isOpen, onClose }) => {
const [ page, setPage ] = useState(0);
const FormTitles = ["Invoice Address", "Bank Data", "Contact"];
const dispatch = useAppDispatch();
const { register, handleSubmit, formState: { errors, isValid }} = useForm<UI>({ mode: "all" });
const onSubmit = handleSubmit((data) => {
dispatch(setList(data));
});
return isOpen ? (<div className="viewModal">
<div className='modalContent'>
<form onSubmit={ onSubmit }>
<div className="contentForm">
<div className="closeX" onClick={ onClose }>x</div>
<div className="labels">
<div className="titleTxt">{ FormTitles[page] }</div>
{ page === 0 && (<>
<div className="labelInput">
<label htmlFor="additional">Additional</label>
<input { ...register("additional")} id="additional" />
</div>
<div className="labelInput">
... // content
</div>
<div className="labelInput">
... // content
</div>
</>)}
{ page === 1 && (<>
<div className="labelInput">
<label htmlFor="iban">IBAN</label>
<div className="dirCol">
<input { ...register("iban", { required: true, maxLength: 30 })} id="iban" />
<div className="required">{ errors.iban && "This is required!" }</div>
</div>
</div>
<div className="labelInput">
... // content
</div>
{ page === 2 && (<>
{/* *** fax *** */}
<div className="labelInput">
<label htmlFor="fax">Fax</label>
<input { ...register("fax")} id="fax" />
</div>
<div className="labelInput">
... // content
</div>
<div className="labelInput">
... // content
</div>
</div>
<div className="labelButton">
<button className="button2" onClick={ onClose }>Cancel</button>
{ page !== 0 && (<div className="button2 textCancel" onClick={() => { setPage((x) => x - 1)}}
>Previous</div>)}
{ page !== 2 && (<button className="button1" type="button" disabled={ !isValid } onClick={() => { setPage((x) => x + 1)}}
>Next</button>)}
{ page === 2 && (<>
<button className="button1" type="submit" value="submit" onClick={ onClose }>Save</button>
</>)}
</div>
</div>
</form>
</div>
</div>) : null
};
export default AddData;
here AddData off and on, onClose working with cancel and x button
import { useState } from 'react';
import AddData from './AddData';
import { useAppDispatch, useAppSelector } from '../redux/hooks';
import { removeList } from '../redux/slice';
const ListTable = () => {
const [ isModalOpen, setIsModalOpen ] = useState(false);
const toogleModal = () =>setIsModalOpen(!isModalOpen);
const dispatch = useAppDispatch();
const selector = useAppSelector((state) => state.users.list );
return <>
<AddData isOpen={ isModalOpen } onClose={ toogleModal }>
</AddData>
<nav>
<button onClick={ toogleModal }>Add</button>
</nav>
<div className='content'>
... // content
</div>
</>
};
export default ListTable;
Inside of the onClick for your save button you can call onSubmit and onClose.
import { useAppDispatch } from "../redux/hooks";
import { userInfo } from "../redux/model";
import { useForm } from "react-hook-form";
import { ModalProps } from "../redux/model";
import { setList } from "../redux/slice";
type UI = userInfo;
const AddData: React.FC<ModalProps> = ({ isOpen, onClose }) => {
const [page, setPage] = useState(0);
const FormTitles = ["Invoice Address", "Bank Data", "Contact"];
const dispatch = useAppDispatch();
const {
register,
handleSubmit,
formState: { errors, isValid },
} = useForm<UI>({ mode: "all" });
const onSubmit = handleSubmit((data) => {
dispatch(setList(data));
});
return isOpen ? (
<div className="viewModal">
<div className="modalContent">
<form onSubmit={onSubmit}>
<div className="contentForm">
<div className="closeX" onClick={onClose}>
x
</div>
<div className="labels">
<div className="titleTxt">{FormTitles[page]}</div>
{page === 0 && (
<>
<div className="labelInput">
<label htmlFor="additional">Additional</label>
<input {...register("additional")} id="additional" />
</div>
<div className="labelInput">{/* ... // content */}</div>
<div className="labelInput">{/* ... // content */}</div>
</>
)}
{page === 1 && (
<>
<div className="labelInput">
<label htmlFor="iban">IBAN</label>
<div className="dirCol">
<input
{...register("iban", { required: true, maxLength: 30 })}
id="iban"
/>
<div className="required">
{errors.iban && "This is required!"}
</div>
</div>
</div>
<div className="labelInput">... // content</div>
</>
)}
{page === 2 && (
<>
{/* *** fax *** */}
<div className="labelInput">
<label htmlFor="fax">Fax</label>
<input {...register("fax")} id="fax" />
</div>
<div className="labelInput">{/* ... // content */}</div>
<div className="labelInput">{/* ... // content */}</div>
</>
)}
</div>
<div className="labelButton">
<button className="button2" onClick={onClose}>
Cancel
</button>
{page !== 0 && (
<div
className="button2 textCancel"
onClick={() => {
setPage((x) => x - 1);
}}
>
Previous
</div>
)}
{page !== 2 && (
<button
className="button1"
type="button"
disabled={!isValid}
onClick={() => {
setPage((x) => x + 1);
}}
>
Next
</button>
)}
{page === 2 && (
<>
<button
className="button1"
type="submit"
value="submit"
onClick={() => {
onSubmit();
onClose;
}}
>
Save
</button>
</>
)}
</div>
</div>
</form>
</div>
</div>
) : null;
};
export default AddData;

How to set state when a button is clicked

I want to set user.Id in setDelid when the button is clicked.
<div className="users">
{users.map((user) => {
return (
<div className="users" key={user.Id} >
<p>
Name: {user.Title}, EmpID: {user.EmpID}, ID: {user.Id}
</p>
<button onClick={deleteData} onChange={(user) => setDelid(user.Id)} className="button button4"></button>
</div>
);
})}
</div>
You can use the onClick function to run the deleteData function and set state:
<button onClick={() => handleClick(user.id)} />
const handleClick = (userId: string) => {
setDelid(userId)
deleteData()
}

get input value using custom numbers in react

i have custom numpad and input box and i want that when user click any number it shows in input field.
<div class="grid-container">
<button class="grid-item" onClick={inputNumKey}>1</button>
<button class="grid-item" onClick={inputNumKey}>2</button>
<button class="grid-item" onClick={inputNumKey}>3</button>
<button class="grid-item" onClick={inputNumKey}>4</button>
<button class="grid-item" onClick={inputNumKey}>5</button>
<button class="grid-item" onClick={inputNumKey}>6</button>
<button class="grid-item" onClick={inputNumKey}>7</button>
<button class="grid-item" onClick={inputNumKey}>8</button>
<button class="grid-item" onClick={inputNumKey}>9</button>
<button class="grid-item" onClick={inputNumKey}>*</button>
<button class="grid-item" onClick={inputNumKey}>0</button>
<button class="grid-item" onClick={inputNumKey}>#</button>
</div>
this is my numpad jsx code.
<div className="input-box-ad">
<input onChange={changeTime} name="hour" value={updatedHour} />
<input onChange={changeTime} name="minute" value={updatedMinute} />
<input onChange={changeTime} name="second" value={updatedSecond} />
</div>
this is input fields i want values of this button.
for more details i have codesandbox also - https://codesandbox.io/s/fancy-frog-l5uo2
const activeInput = { "background-color": "#BBFFCC" };
const Numbers = () => {
const [hour, setHour] = useState("00");
const [minute, setMinute] = useState("00");
const [second, setSecond] = useState("00");
const [timeType, setTimeType] = useState("hour");
const press = (k) => {
const [value, setter] =
timeType === "hour"
? [hour, setHour]
: timeType === "minute"
? [minute, setMinute]
: [second, setSecond];
setter((value.charAt(value.length - 1) || "0") + k);
};
return (
<div>
<div class="grid-container">
<button onClick={() => press("1")}>1</button>
<button onClick={() => press("2")}>2</button>
<button onClick={() => press("3")}>3</button>
<button onClick={() => press("4")}>4</button>
<button onClick={() => press("5")}>5</button>
<button onClick={() => press("6")}>6</button>
<button onClick={() => press("7")}>7</button>
<button onClick={() => press("8")}>8</button>
<button onClick={() => press("9")}>9</button>
<button onClick={() => press("*")}>*</button>
<button onClick={() => press("0")}>0</button>
<button onClick={() => press("#")}>#</button>
</div>
<div className="input-box-ad">
<input name={"hour"} value={hour} size={2}
onClick={() => setTimeType("hour")}
onChange={(e) => setHour(e.target.value)}
style={timeType === "hour" ? activeInput : {}}
/>
:
<input name={"minute"} value={minute} size={2}
onClick={() => setTimeType("minute")}
onChange={(e) => setMinute(e.target.value)}
style={timeType === "minute" ? activeInput : {}}
/>
:
<input name={"second"} value={second} size={2}
onClick={() => setTimeType("second")}
onChange={(e) => setSecond(e.target.value)}
style={timeType === "second" ? activeInput : {}}
/>
</div>
</div>
);
};
This is going to be very difficult to manage. I don't know why do you need the buttons to enter input you can do it with the keyboard.
If you do it with a keyboard then it will be easy.
const[updatedHour,setUpdatedHour] = useState();
function changeHour(e){
setUpdatedHour(e.target.value)
}
<input onChange={changeHour} name="hour" value={updatedHour} />
Do the same for all input boxes.
Still, if you want to do it with buttons here is a hint.
function inputNumKey(e){
console.log(e.target.textContent)
}

How can I have conditional buttons without repeating code. React

I am trying to make it so the buttons are only visible in my create page. I have figured out how to do this although in such a way that code is repeated
if (mode != "view") {
return (
<>
<section
className={`col-md-${sectionInputArray.width} justify-content border-end mt-2 mb-2`}
>
<h4 className="border-bottom">{`${sectionInputArray.name}`} </h4>
<div className="col-12"></div>
{sectionInputArray.contents.map((input, i) => (
<NestedDynamicInputCreation
singleInput={input}
formData={formData}
setFormData={setFormData}
options={options}
mode={mode}
staticVars={staticVars}
SetStaticVars={SetStaticVars}
i={i}
idx={idx}
arrayLength={arrayLength}
sectionUID={sectionInputArray.UID}
/>
))}
{/* Button to add new field */}
<button
id ="TestButton1"
className="btn btn-primary bt-btn m-3"
type="button"
onClick={() => {
// console.log(`${sectionInputArray.name} section will be added`);
// console.log({ formDataTarget: formData[sectionInputArray.UID] });
// New Inbound Rule
// console.log([
// ...formData[sectionInputArray.UID],
// NestedListIDSingle(sectionInputArray),
// ]);
let addedFormData = {
...formData,
[`${sectionInputArray.UID}`]: [
...formData[sectionInputArray.UID],
NestedListIDSingle(sectionInputArray),
],
};
let randomVal = Math.random()
.toString(36)
// .replace(/[^a-z]+/g, "")
.substr(0, 11);
let withRandom = {
...addedFormData,
rand_value: randomVal,
};
// console.log({ addedFormData: addedFormData });
setFormData(withRandom);
}}
>
Add New {sectionInputArray.name}
</button>
{/* Button to remove section (or created form) */}
<button
className="btn btn-primary bt-btn m-3"
type="button"
onClick={() => {
console.log(
`${sectionInputArray.name}-${idx} section will be removed`
);
// formData[sectionInputArray.UID].splice(idx, 1);
let formDataTarget = formData[sectionInputArray.UID];
// console.log(formDataTarget);
let newFD = formData;
newFD[sectionInputArray.UID].splice(idx, 1);
let randomVal = Math.random()
.toString(36)
// .replace(/[^a-z]+/g, "")
.substr(0, 11);
let withRandom = {
...newFD,
rand_value: randomVal,
};
setFormData(withRandom);
}}
>
Remove {sectionInputArray.name}
</button>
</section>
</>
);
} else {
return (
<>
<section
className={`col-md-${sectionInputArray.width} justify-content border-end mt-2 mb-2`}
>
<h4 className="border-bottom">{`${sectionInputArray.name}`} </h4>
<div className="col-12"></div>
{sectionInputArray.contents.map((input, i) => (
<NestedDynamicInputCreation
singleInput={input}
formData={formData}
setFormData={setFormData}
options={options}
mode={mode}
staticVars={staticVars}
SetStaticVars={SetStaticVars}
i={i}
idx={idx}
arrayLength={arrayLength}
sectionUID={sectionInputArray.UID}
/>
))}
</section>
</>
)
As you can see above when it is not on the view page it will then not use the buttons as it is removed within the 'else' section.
How could i create an instance of this, when the button is conditional. I tried placing an if statement just before the button section however that did not work
Yes you can do it - place your conditional rendering (operator &&) after your <NestedDynamicInputCreation
return (
<>
<section
className={`col-md-${sectionInputArray.width} justify-content border-end mt-2 mb-2`}
>
<h4 className="border-bottom">{`${sectionInputArray.name}`} </h4>
<div className="col-12"></div>
{sectionInputArray.contents.map((input, i) => (
<NestedDynamicInputCreation
singleInput={input}
formData={formData}
setFormData={setFormData}
options={options}
mode={mode}
staticVars={staticVars}
SetStaticVars={SetStaticVars}
i={i}
idx={idx}
arrayLength={arrayLength}
sectionUID={sectionInputArray.UID}
/>
))}
{mode != 'view' && (
<>
<button
id ="TestButton1"
className="btn btn-primary bt-btn m-3"
type="button"
onClick={() => {
...
})
>
Add New {sectionInputArray.name}
</button>
<button
className="btn btn-primary bt-btn m-3"
type="button"
onClick={() => {
..
})
>
Remove {sectionInputArray.name}
</button>
</>
)}
</section>
</>
);
If the content the same you could use Fragments and conditionally show the buttons:
return (
<>
<section
className={`col-md-${sectionInputArray.width} justify-content border-end mt-2 mb-2`}
>
<h4 className="border-bottom">{`${sectionInputArray.name}`} </h4>
<div className="col-12"></div>
{sectionInputArray.contents.map((input, i) => (
<NestedDynamicInputCreation
singleInput={input}
formData={formData}
setFormData={setFormData}
options={options}
mode={mode}
staticVars={staticVars}
SetStaticVars={SetStaticVars}
i={i}
idx={idx}
arrayLength={arrayLength}
sectionUID={sectionInputArray.UID}
/>
))}
{mode !== 'view' && (
<>
<button
id ="TestButton1"
className="btn btn-primary bt-btn m-3"
type="button"
onClick={() => {
// console.log(`${sectionInputArray.name} section will be added`);
// console.log({ formDataTarget: formData[sectionInputArray.UID] });
// New Inbound Rule
// console.log([
// ...formData[sectionInputArray.UID],
// NestedListIDSingle(sectionInputArray),
// ]);
let addedFormData = {
...formData,
[`${sectionInputArray.UID}`]: [
...formData[sectionInputArray.UID],
NestedListIDSingle(sectionInputArray),
],
};
let randomVal = Math.random()
.toString(36)
// .replace(/[^a-z]+/g, "")
.substr(0, 11);
let withRandom = {
...addedFormData,
rand_value: randomVal,
};
// console.log({ addedFormData: addedFormData });
setFormData(withRandom);
}}
>
Add New {sectionInputArray.name}
</button>
{/* Button to remove section (or created form) */}
<button
className="btn btn-primary bt-btn m-3"
type="button"
onClick={() => {
console.log(
`${sectionInputArray.name}-${idx} section will be removed`
);
// formData[sectionInputArray.UID].splice(idx, 1);
let formDataTarget = formData[sectionInputArray.UID];
// console.log(formDataTarget);
let newFD = formData;
newFD[sectionInputArray.UID].splice(idx, 1);
let randomVal = Math.random()
.toString(36)
// .replace(/[^a-z]+/g, "")
.substr(0, 11);
let withRandom = {
...newFD,
rand_value: randomVal,
};
setFormData(withRandom);
}}
>
Remove {sectionInputArray.name}
</button>
</>
)}
</section>
</>
);

my form not submitting so where is the problem

as you see my form not submit i can't see where is the problem i search but all the solution i found i already made it so what else can be the problem when i try to use console it don't show like it doesn't enter the submit function at all
this is the pieces in my component that work with form
const [editMyText, setEditMyText] = useState({
editIsActive: false,
textValue: body,
});
const inputRef = useRef(null);
const handleSaveEdit = (e) => {
setEditMyText({
editIsActive: false,
textValue: inputRef.current.value,
});
// updatePost(_id, textValue);
};
const handleOnSubmit = (e) => {
e.preventDefault();
console.log('done 1');
updatePost(_id, textValue);
console.log('done 2');
};
{body !== null && !editIsActive ? (
<p
className='card-text'
onClick={(e) => auth.user._id === user && handleEditText(e)}
>
{textValue}
</p>
) : (
<form
className='edit-post-form'
onSubmit={(e) => handleOnSubmit(e)}
>
<textarea
className='edit-text'
defaultValue={textValue}
ref={inputRef}
/>
<button
className='btn btn-raised btn-danger mr-2'
onClick={(e) => handleCloseEdit(e)}
>
Close
</button>
<button
type='submit'
className='btn btn-raised btn-success'
onClick={(e) => handleSaveEdit(e)}
>
Save
</button>
</form>
)}

Resources