[英]How to handle multiple radio button groups in one component in reactjs?
我正在嘗試在單擊發送按鈕時從多個單選按鈕組中發送選定單選按鈕 ID 的列表,
我的問題:我從后端獲得選中的單選按鈕,然后我應該能夠更改單選按鈕並發送回后端。 但是當我嘗試更改單選按鈕時它不起作用。
我不明白的是:如何處理更改 function,通常更改時我們可以更改 state 但要更改 state 加載時我們應該獲取值。 最后我被擊中了,不知道如何前進。
這是線框圖和代碼片段:
function CardsList(props) { const cards = props.cards; return ( <div> {cards.map((card, idx) => ( <div> {card.cardName} { card.options.map((lo,idx) => ( <li key={idx}> <input className="default" type="radio" name={card.cardName} checked={lo.selected} />)) } <div> ))} </div> ); } //array of cards coming from the backend const cards = [ {cardName:'card1',options:[{radioName:'card1-radio1',selected:'true'}, {radioName:'card1-radio2',selected:'false'}]}, {cardName:'card2',options:[{radioName:'card2-radio1',selected:'true'}, {radioName:'card2-radio2',selected:'false'}]} ]; ReactDOM.render( <CardsList cards={cards} />, document.getElementById('root') );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root"></div>
您無法更改它們的原因是您在此處設置的當前已檢查狀態:
<input
className="default"
type="radio"
name={card.cardName}
checked={lo.selected}
/>
我用於這個確切場景的方法是將組件的狀態(來自服務器)存儲在組件的狀態( this.state
)中,將狀態傳遞給元素: checked={this.state.isChecked}
,並更新元素的狀態onClick
。
例:
class CardsList extends Component {
constructor(props){
super(props);
this.state = {isChecked: false};
this.inputOnClick = this.inputOnClick.bind(this);
}
//fetch data from server
fetchData(){
fetch('/api')
.then(res => res.json())
//this will be our initial state
.then(res => this.setState(res))
}
componentDidMount(){
this.fetchData();
}
//change radio button state on click
inputOnClick(e){
e.preventDefault();
//invert state value
this.setState((prevState, props) => {isChecked: !prevState.isChecked});
}
render(){
return (
<input
type="radio"
checked={this.state.isChecked}
onClick={this.inputOnClick}
/>
)
}
}
這個答案可能適用於單個單選按鈕組,但我遇到多個單選按鈕組中的多個單選按鈕的問題。如果你看到卡陣列,它如何知道它屬於哪個單選按鈕組。
我們可以根據單選按鈕的名稱修改狀態。
讓我們將所有卡片保存在組件的狀態中。 我知道這些卡是從服務器中檢索出來的,並且將使用setState
保存,但我這樣寫是為了視覺目的。
this.state = {cards: [
{ cardName:'card1',
options:[
{radioName:'card1-radio1',selected:true},
{radioName:'card1-radio2',selected:false}
]
},
{ cardName:'card2',
options:[
{radioName:'card2-radio1',selected:true},
{radioName:'card2-radio2',selected:false}
]
}
]}
現在,當我們點擊單選按鈕時,我們將使用該單選按鈕的名稱來更新需要更新的狀態。 由於React狀態需要是不可變的,我們將創建狀態的深層副本,修改它,然后用它設置狀態。
inputOnClick(e){
e.preventDefault();
var thisRadioBtn = e.target.name;
//make a deep copy of the state
const stateCopy = JSON.parse(JSON.stringify(this.state.cards));
//go through state copy and update it
stateCopy.forEach(card => {
card.options.forEach(option => {
if(option.radioName === thisRadioBtn){
//invert value
//make sure the values are booleans
option.selected = !option.selected;
}
});
});
//update the components state
this.setState({cards: stateCopy});
}
您可以將對象用作將組名稱保存為鍵的查找表。
在每次更改時,您都需要找到具有相關選項的相關組,並相應地設置新狀態。
重要! - 這里需要注意的一點是,我將selected
屬性的類型從String
更改為Boolean
。 這將讓我處理這樣的條件:
<input checked={option.selected} />
如果你不能將它改為Boolean
那么你需要處理這樣的條件:
<input checked={option.selected === 'true'} />
這是一個運行的例子:
//array of cards coming from the backend const data = [ { cardName: 'card1', options: [{ radioName: 'card1-radio1', selected: true }, { radioName: 'card1-radio2', selected: false }] }, { cardName: 'card2', options: [{ radioName: 'card2-radio1', selected: true }, { radioName: 'card2-radio2', selected: false }] } ]; class CardsList extends React.Component { constructor(props) { super(props); this.state = { cards: [] }; } componentDidMount() { setTimeout(() => { // mimic an async server call this.setState({ cards: data }); }, 1000); } onInputChange = ({ target }) => { const { cards } = this.state; const nexState = cards.map(card => { if (card.cardName !== target.name) return card; return { ...card, options: card.options.map(opt => { const checked = opt.radioName === target.value; return { ...opt, selected: checked } }) } }); this.setState({ cards: nexState }) } onSubmit = () => { console.log(this.state.cards) }; render() { const { cards } = this.state; return ( <div> { cards.length < 1 ? "Loading..." : <div> {cards.map((card, idx) => ( <ul> {card.cardName} { card.options.map((lo, idx) => { return <input key={idx} type="radio" name={card.cardName} value={lo.radioName} checked={!!lo.selected} onChange={this.onInputChange} /> }) } </ul> )) } < button onClick={this.onSubmit}>Print Cards</button> </div> } </div> ); } } ReactDOM.render(<CardsList />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root"></div>
在 2022 年 6 月,我遇到了與您類似的問題。 我的解決方案是在兩個部分都添加標簽<form>
,而無需對其進行 OnSubmit 或操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.