英文:
useRef hook for more than 1 input elements
问题
在 onClickNewGalley
函数中,您尝试在每个输入字段上使用 useRef
来获取它们的当前值,但只有 inputRef4
能正常工作。这可能是因为在 useEffect
中处理所有 inputRef
的焦点集中在最后一个 inputRef4
上。
要解决这个问题,您可以考虑在 onClickNewGalley
中使用一个循环来分别设置每个输入字段的焦点和状态。这里是一个可能的修改:
const onClickNewGalley = () => {
setState({
name: '',
fullCarts: null,
halfCarts: null,
smu: null,
stowage: null,
firstClass: false,
businessClass: false,
premEconomy: false,
economy: false,
});
// Toggle buttonClicked state
setButtonClicked(!buttonClicked);
// Focus on all input fields
const inputRefs = [inputRef0, inputRef1, inputRef2, inputRef3, inputRef4];
inputRefs.forEach((ref) => ref.current.focus());
};
这样,您可以确保所有输入字段都会获得焦点,并且它们的值都会被清空,而不仅仅是最后一个 inputRef4
。
英文:
i am using useRef hook in functional component to show input control when a button is clicked in react js.I have total 5 input fields which are individually defined.To meet my purpose of triggering input fields in all the 5 input elements i am assigning 5 useRef hooks to 5 constant variables and assigning the ref property to the corresponding input fields. my code is as follows,
import React, { useState ,useEffect,useRef} from 'react';
import '../../../assets/styles/modal.scss';
import closeIcon from '../../../images/icons/Icon2.png';
import deleteIcon from '../../../assets/icons/deleteRole.svg';
import { DFPAPIEndpoint, DFPAPIEndpointGalley } from "../../../utils/axios";
import { useTranslation } from 'react-i18next';
export const ConfigGalley = (props) => {
const { t } = useTranslation();
const [state,setState]=useState({name:'',fullCarts:null,halfCarts:null,smu:null,stowage:null,firstClass:false,businessClass:false,premEconomy:false,economy:false});
const [editState,setEditState]=useState({});
const [carts,setCarts]=useState([]);
const [selectedGalley,setSelectedGalley]=useState({});
const [buttonStatus,setButtonStatus]=useState(false);
const[modalFormStatusObj,setModalFormStatusObj]=useState({text:''})
const [inputFields,setInputFields]=useState(false);
const [buttonClicked,setButtonClicked]=useState(false);
const inputRef0=useRef(null);
const inputRef1=useRef(null);
const inputRef2=useRef(null);
const inputRef3=useRef(null);
const inputRef4=useRef(null);
const handleReset = () => {
let timerId = setTimeout(() => {
clearTimeout(timerId);
setState((_) => {
return { ..._, modalFormStatusObj: {text:''} };
})
}, 500)
setState({name:'',fullCarts:null,halfCarts:null,smu:null,stowage:null,firstClass:false,businessClass:false,premEconomy:false,economy:false})
checkEmptyFields(state);
}
useEffect(() => {
showUserRoles(props.airCraft?.galleys);
checkEmptyFields(state);
}, [props])
useEffect(() => {
if(buttonClicked){
inputRef0.current.focus();
inputRef1.current.focus();
inputRef2.current.focus();
inputRef3.current.focus();
inputRef4.current.focus();
}
}, [buttonClicked])
useEffect(() => {
if(!checkEmptyFields(state)){
setButtonStatus(false);
}
else{
setButtonStatus(true);
}
}, [state])
useEffect(() => {
if(props.airCraft){
setCarts(props.airCraft.galleys);
setInputFields(checkEmptyFields(state))
}
if(props.airCraft.galleys){
showUserRoles(props.airCraft.galleys);
}
}, [props.airCraft])
const checkEmptyFields=(state)=>{
for(let i in state) {
if(i==='name'||i==='halfCarts'||i==='fullCarts'||i==='smu'||i==='stowage'){
if (state['name'] !== '' && state["halfCarts"] && state["fullCarts"] && state["smu"] && state["stowage"])
return false;
}
}
return true;
}
const onChange = (e) => {
const { name, value } = e.target;
switch (name) {
case "name":
setState((_prev) => {
return { ..._prev, name:value };
});
break;
case "fullcarts":
setState((_prev) => {
return { ..._prev, fullCarts:value };
});
break;
case "halfcarts":
setState((_prev) => {
return { ..._prev, halfCarts:value };
});
break;
case "smu":
setState((_prev) => {
return { ..._prev, smu:value };
});
break;
case "stowage":
setState((_prev) => {
return { ..._prev, stowage:value };
});
break;
case "firstClass":
setState((_prev) => {
return { ..._prev, firstClass:true,businessClass:false,premEconomy:false,economy:false };
});
break;
case "businessClass":
setState((_prev) => {
return { ..._prev, firstClass:false,businessClass:true,premEconomy:false,economy:false };
});
break; case "premEconomy":
setState((_prev) => {
return { ..._prev,firstClass:false,businessClass:false,premEconomy:true,economy:false };
});
break; case "economy":
setState((_prev) => {
return { ..._prev, firstClass:false,businessClass:false,premEconomy:false,economy:true };
});
break;
default:
setState((_prev) => {
return { ..._prev,name:'',fullCarts:null,halfCarts:null,smu:null,stowage:null,firstClass:false,businessClass:false,economy:false,premEconomy:false };
});
break;
}
}
let isError = false,
updateStatusText="";
if (modalFormStatusObj) {
if (('text' in modalFormStatusObj)) {
updateStatusText= modalFormStatusObj.text;
}
}
const getClassCodeEdit=(ob)=>{
switch (ob?.classCode) {
case 'fc':
setState((_prev) => {
return { ..._prev,firstClass:!state.firstClass,businessClass:false,premEconomy:false,economy:false};
});
break;
case 'bcl':
setState((_prev) => {
return { ..._prev,firstClass:false,businessClass:!state.businessClass,premEconomy:false,economy:false};
});
break;
case 'pcy':
setState((_prev) => {
return { ..._prev,firstClass:false,businessClass:false,premEconomy:!state.premEconomy,economy:false};
});
break;
case 'ecy':
setState((_prev) => {
return { ..._prev,firstClass:false,businessClass:false,premEconomy:false,economy:!state.economy};
});
break;
default:
setState((_prev) => {
return { ..._prev};
});
break;
}
}
const onConfigClick=async(e,r)=>{
if(e.target.nodeName!=='IMG'&&e.target.nodeName!=='BUTTON'){
setSelectedGalley(r)
getClassCodeEdit(r)
setState((_prev) => {
return { ..._prev,name:r.name,fullCarts:r.carts[0].quantity,halfCarts:r.carts[1].quantity,smu:r.carts[2].quantity,stowage:r.carts[3].quantity};
});
setEditState((_prev) => {
return { ..._prev,id:r._id,name:r.name,fullCarts:r.carts[0].quantity,halfCarts:r.carts[1].quantity,smu:r.carts[2].quantity,stowage:r.carts[3].quantity};
})
setInputFields(false);
}
else{
setSelectedGalley(r)
if(r){
setButtonStatus(true)
try {
const resp = await DFPAPIEndpointGalley.delete(`galley/aircraftTypes/${props.airCraft.id}/galleys/${r._id}`);
if(resp.success){
setModalFormStatusObj({text:resp.message})
handleReset()
setButtonStatus(false)
props.setState((_) => {
return { ..._, resetDataSource: true };
})
}
} catch (error) {
setModalFormStatusObj({text: error.data.message})
handleReset()
}
}
}
}
const onEditSubmit=async()=>{
setButtonStatus(true);
const cartsObj=[
{
"id": "full",
"name": "Full Cart",
"weight": 0,
"volume": 0,
"dimensions": {
"length": 0,
"breadth": 0,
"height": 0
},
"quantity": parseInt(state.fullCarts)
},
{
"id": "half",
"name": "Half Cart",
"weight": 0,
"volume": 0,
"dimensions": {
"length": 0,
"breadth": 0,
"height": 0
},
"quantity": parseInt(state.halfCarts)
},
{
"id": "smu",
"name": "SMU",
"weight": 0,
"volume": 0,
"dimensions": {
"length": 0,
"breadth": 0,
"height": 0
},
"quantity": parseInt(state.smu)
},
{
"id": "stowage",
"name": "Misc. Stowage",
"weight": 0,
"volume": 0,
"dimensions": {
"length": 0,
"breadth": 0,
"height": 0
},
"quantity": parseInt(state.stowage)
}
]
let classCode;
switch (Object.keys(state).map((m,index)=> {if(state[m]===true){return m}}).filter(f=>f!==undefined)[0]) {
case 'firstClass':
classCode='fc'
break;
case 'businessClass':
classCode='bcl'
break;
case 'premEconomy':
classCode='pcy'
break;
case 'economy':
classCode='ecy'
break;
default:
classCode=""
break;
}
let temp= {
"name": state.name,
classCode,
carts: cartsObj
}
let body=[];
if(temp.name.length){
body.push(temp,...carts);
}
else{
body.push(...carts);
}
const updatedBody = body.map((item) => {
if (item.name === editState.name) {
return {
...item,
carts: cartsObj,
};
}
return item
})
let removeIndex = updatedBody.map(item => item.name).indexOf(selectedGalley.name);
removeIndex>=0 && updatedBody.splice(removeIndex, 1);
if(!checkEmptyFields(state)){
try {
const resp = await DFPAPIEndpointGalley.post(`galley/aircraftTypes/${props.airCraft.id}/galleys`,updatedBody[0]);
if(resp.success){
setModalFormStatusObj({text:resp.message})
setEditState({});
handleReset()
props.setState((_) => {
return { ..._, resetDataSource: true };
})
setButtonStatus(false);
}
} catch (error) {
setModalFormStatusObj({text: error})
handleReset()
}
}
}
const showUserRoles=(galleyArr)=>{
const result=galleyArr.map(gal=>{
return(<div className="form-group galley-modal" id="one" onClick={(e)=>onConfigClick(e,gal)} style={{overflow:'auto'}}>
<ul className='list-group' style={{padding: "0 15px"}}>
<div className='role_card'>
<div style={{display:'inline-block'}}>
<p className='role_name'> {<h6 className="subheading-text-medium-title fontLight margLeft8">{gal.name}</h6>}</p>
{gal.carts.map((_,index) =>
<li className='list-group-item-role'style={{display:"inline"}} key={index} >
{<><button className='cart_display_galley'>
{_.name}<span className='galley_cart_count'>{_.quantity}</span>
</button>
</>}
</li>)}
<span className='remove_role_icon'>
<button style={{float:'right'}} id="two" className='mt-4 remove-button-galley' onClick ={(e)=>onConfigClick(e,gal)}>
<img className="icon-size-role" alt='deleteIcon' src={deleteIcon} />
</button>
</span>
</div>
</div>
</ul>
</div>)
}
)
return result
}
const onClickNewGalley=()=>{
setState((_prev) => {
return { ..._prev,name:'',fullCarts:null,halfCarts:null,smu:null,stowage:null,firstClass:false,businessClass:false,premEconomy:false,economy:false};
});
setInputFields(false);
setButtonClicked(!buttonClicked)
}
return (
<div className="overlay" role="dialog">
<div className="dialog sm-scrollbar">
<div className="dialog__content margBottom48">
<img className="modal__close_icon" alt='Close' src={closeIcon} onClick={props.onUploadClose} />
<h2 className="dialog__title subheading-text-medium fontMedium">{props.modelTitle}</h2>
<hr />
<button style={{width:'1rem'}} id='newGalleyAdd' className="done-button subheading-text-medium-title fontLight" onClick={onClickNewGalley}>+ New Galley</button>
<div className="containe" style={{display:'flex',height:'400px'}}>
<div className='width50'>
<div className="">
<div>
{props.airCraft &&props.airCraft?.galleys&&showUserRoles(props.airCraft?.galleys)}
</div>
</div>
</div>
<div className='width10'></div>
<div className='width40'>
<div class=" dialog__container_item input-container">
<div class="dialog__description_config">
<label className='margBottom10'>Name *</label>
<input
id={''}
name="name"
placeholder='Name'
ref={inputRef0}
onChange={(e)=>onChange(e)}
disabled={inputFields}
value={state.name?state.name:''}
type={'text'}
className='edit-input'
/>
</div>
</div>
<div class="flexCol justifyContentSpaceEvenly ">
<div class=" dialog__container_item input-container">
<div class="dialog__description_config">
<label className='marginTop30' for='fullcarts' >Full Carts</label>
<input
id={'fullcarts'}
name='fullcarts'
placeholder='Full Carts'
ref={inputRef1}
onChange={(e)=>onChange(e)}
disabled={inputFields}
value={state.fullCarts?state.fullCarts:""}
type={'number'}
className='edit-input-galley'
/>
</div>
</div>
</div>
<div class="flexCol justifyContentSpaceEvenly ">
<div class=" dialog__container_item input-container">
<div class="dialog__description_config">
<label className='marginTop30'>Half Carts</label>
<input
id={'halfcarts'}
name='halfcarts'
placeholder='Half Carts'
ref={inputRef2}
onChange={(e)=>onChange(e)}
disabled={inputFields}
value={state.halfCarts?state.halfCarts:""}
type={'number'}
className='edit-input-galley'
/>
</div>
</div>
</div>
<div class="flexCol justifyContentSpaceEvenly ">
<div class=" dialog__container_item input-container">
<div class="dialog__description_config">
<label className='marginTop30'>SMU</label>
<input
id="smu"
name='smu'
placeholder='SMU'
ref={inputRef3}
onChange={(e)=>onChange(e)}
disabled={inputFields}
value={state.smu?state.smu:''}
type={'number'}
className='edit-input-galley' />
</div>
</div>
</div>
<div class="flexCol justifyContentSpaceEvenly ">
<div class=" dialog__container_item input-container">
<div class="dialog__description_config">
<label className='marginTop30'>Misc. Stowage</label>
<input
id="stowage"
name='stowage'
placeholder='Stowage'
ref={inputRef4}
onChange={(e)=>onChange(e)}
disabled={inputFields}
value={state.stowage?state.stowage:''}
type={'number'}
className='edit-input-galley' />
</div>
</div>
</div>
<div style={{marginTop:'2.5rem'}} className='flexRow'>
<div class="flexCol justifyContentSpaceEvenly ">
<div class=" dialog__container_item input-container">
<div className='flexRow'>
<div className={`dialog__description__radio`}>
<label class="control control-radio margRight30" for="1">
<input id="1" type="radio"
name="firstClass"
value= {state.firstClass}
checked={state.firstClass}
disabled={inputFields}
onChange={onChange} />
<span>First Class</span>
<div class="control-indicator"></div>
</label>
</div>
</div>
</div>
</div>
<div class="flexCol justifyContentSpaceEvenly ">
<div class=" dialog__container_item input-container">
<div className='flexRow'>
<div className={`dialog__description__radio`}>
<label class="control control-radio margRight30" for="2">
<input id="2" type="radio"
name="businessClass"
value= {state.businessClass}
checked={state.businessClass}
disabled={inputFields}
onChange={onChange} />
<span>Business Class</span>
<div class="control-indicator"></div>
</label>
</div>
</div>
</div>
</div>
<div class="flexCol justifyContentSpaceEvenly ">
<div class=" dialog__container_item input-container">
<div className='flexRow'>
<div className={`dialog__description__radio`}>
<label class="control control-radio margRight30" for="3">
<input id="3" type="radio"
name="premEconomy"
value= {state.premEconomy}
checked={state.premEconomy}
disabled={inputFields}
onChange={onChange} />
<span>Premium Economy</span>
<div class="control-indicator"></div>
</label>
</div>
</div>
</div>
</div>
<div class="flexCol justifyContentSpaceEvenly ">
<div class=" dialog__container_item input-container">
<div className='flexRow'>
<div className={`dialog__description__radio`}>
<label class="control control-radio margRight30" for="4">
<input id="4" type="radio"
name="economy"
value= {state.economy}
checked={state.economy}
disabled={inputFields}
onChange={onChange} />
<span>Economy</span>
<div class="control-indicator"></div>
</label>
</div>
</div>
</div>
</div>
</div>
<div className='dialog_buttons margTop50 floatLeft flexRow'>
<button className="save-button" disabled={buttonStatus} onClick={onEditSubmit}>Save</button>
<button className="cancel-button-aircraft" onClick={onClickNewGalley}>Cancel</button>
</div>
<div className='margTop24'>
{Boolean(updateStatusText) ?
<>
<div className={ "dialog__statusBlock " + (isError ? 'alert_error' : 'alert_success') }>
{updateStatusText}
</div>
</> : null }
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export const ConfigureGalley = (props) => {
const onUploadClose = (e) => {
removeContainerOverlay();
props.onUploadClose();
}
const removeContainerOverlay = () => {
/**
* Remove overlay to parent class
*/
(document.querySelectorAll('.content-container')[0]).classList.remove('modal-overlay-bg2');
};
return (
<ConfigGalley
modelTitle={props.modelTitle}
airCraft={props.airCraft}
setState={props.setState}
onUploadClose={onUploadClose}
/>
)
}
in the function onClickNewGalley() i am toggling the state of buttonClicked and using useEffect to get the current value of each input fields.But somehow only the inputRef4 is functioning in this implementation.what else could be done?
答案1
得分: 1
你只能一次只关注一个元素。
当选择一个文本字段并接受输入时,它被称为具有“焦点”。
英文:
You can only focus on one element at a time.
When a text field is selected and accepts input, it is said to have “focus.”
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论