javascript - How to pass value of radio button to component in react
问题描述
I cannot wrap my head around how to pass the value of a selected radio button to another component in React. I'm fiddeling around with the Star Wars API at the moment. Trying to build a simple OPA where the user can fetch information about characters and places in the SW universe.
The user is able to choose which type of information he wants, e.g. searching for planets and then input the name and other information of the chosen planet.
I am trying to build this functionality with a combination of radio buttons and a text input.
I put the text input and the radio buttons in two distinct components - how do I get them to communicate with each other - or to put in another way:
How can I pass the value of one radio button to the other component which adds it to the URL I want to fetch?
My code for the radio button component:
import { React, useState } from 'react';
import styled from 'styled-components';
import {
FormControl,
FormControlLabel,
RadioGroup,
Radio,
} from '@material-ui/core';
const ChooseOption = () => {
const [selected, setSelected] = useState('films');
const isButtonSelected = (value) => {
if (selected === value) {
return true;
}
};
const handleChange = (e) => {
setSelected(e.target.value);
};
return (
<Container>
<FormControl component="fieldset">
<RadioGroup
className="radio-group"
row
aria-label="star wars ressource"
name="row-radio-buttons-group"
value={selected}
>
<FormControlLabel
value="films"
control={<Radio />}
label="Films"
checked={isButtonSelected('films')}
onChange={handleChange}
/>
<FormControlLabel
value="people"
control={<Radio />}
label="People"
checked={isButtonSelected('people')}
onChange={handleChange}
/>
<FormControlLabel
value="planets"
control={<Radio />}
label="Planets"
checked={isButtonSelected('planets')}
onChange={handleChange}
/>
<FormControlLabel
value="species"
control={<Radio />}
label="Species"
checked={isButtonSelected('species')}
onChange={handleChange}
/>
<FormControlLabel
value="starships"
control={<Radio />}
label="Starships"
checked={isButtonSelected('starships')}
onChange={handleChange}
/>
<FormControlLabel
value="vehicles"
control={<Radio />}
label="Vehicles"
checked={isButtonSelected('vehicles')}
onChange={handleChange}
/>
</RadioGroup>
</FormControl>
</Container>
);
};
export default ChooseOption;
const Container = styled.div`
text-align: center;
.radio-group {
width: 85%;
margin: auto;
color: white;
}
.MuiFormControlLabel-root {
display: grid;
margin: 1rem 1.5rem;
.MuiButtonBase-root {
background-color: #000;
}
}
`;
My Code for the form component which consists of the radio button component and the text input:
import React, { useState, useEffect } from 'react';
import styled from 'styled-components';
import { baseURL, appendix, routeObject } from '../api';
import { Button } from '@material-ui/core';
import ChooseOption from './ChooseOption';
const SearchItem = () => {
const [search, setSearch] = useState('');
const [selected, setSelected] = useState();
const [data, setData] = useState([]);
const handleChange = (e) => {
setSearch(e.target.value);
};
const handleSubmit = (e) => {
e.preventDefault();
};
const handleRadio = (e) => {
setSelected(e.target.value);
console.log(selected);
};
// const searchForRessource = () => {
// fetch(baseURL + search)
// .then((response) => {
// return response.json();
// })
// .then((data) => console.log(data));
// };
useEffect(() => {
fetch(baseURL)
.then((response) => {
return response.json();
})
.then((data) => setData(data));
}, []);
console.log(data);
return (
<>
<Container>
<form className="input-form" onSubmit={handleSubmit}>
<ChooseOption onChange={handleRadio} />
<input
className="text-input"
type="text"
id="item-input"
onChange={handleChange}
value={search}
/>
</form>
<Button>Search</Button>
</Container>
</>
);
};
export default SearchItem;
const Container = styled.div`
.input-form {
margin: 2rem auto;
text-align: center;
.text-input {
background-color: var(--starWarsYellow);
width: 70%;
border: none;
padding: 0.75rem;
color: #000;
border-radius: 3px;
}
.text-input:focus {
outline: none;
}
}
.MuiButtonBase-root {
background-color: var(--starWarsYellow);
width: 45%;
display: block;
margin: auto;
}
.MuiButtonBase-root:active {
background-color: green;
}
`;
解决方案
您将 onChange 处理程序传递给您的ChooseOption
组件,但从未调用它。您可以在SearchItem
组件内保持单选按钮的状态(因为您已经有一个状态对象(选中),或者您可以在内部添加一个 useEffect 钩子ChooseOption
,每次您的selected
状态在其中更新时调用 onChange (或者更好在您的handleChange
功能中:
import { React, useState } from 'react';
import styled from 'styled-components';
import {
FormControl,
FormControlLabel,
RadioGroup,
Radio,
} from '@material-ui/core';
const ChooseOption = ({ onChange }) => { // define the passed onChange handler
const [selected, setSelected] = useState('films');
const isButtonSelected = (value) => {
if (selected === value) {
return true;
}
};
const handleChange = (e) => {
setSelected(e.target.value);
onChange(e); // this fires the onChange handler (handleRadio) you passed in SearchItem
};
return (
<Container>
<FormControl component="fieldset">
<RadioGroup
className="radio-group"
row
aria-label="star wars ressource"
name="row-radio-buttons-group"
value={selected}
>
<FormControlLabel
value="films"
control={<Radio />}
label="Films"
checked={isButtonSelected('films')}
onChange={handleChange}
/>
<FormControlLabel
value="people"
control={<Radio />}
label="People"
checked={isButtonSelected('people')}
onChange={handleChange}
/>
<FormControlLabel
value="planets"
control={<Radio />}
label="Planets"
checked={isButtonSelected('planets')}
onChange={handleChange}
/>
<FormControlLabel
value="species"
control={<Radio />}
label="Species"
checked={isButtonSelected('species')}
onChange={handleChange}
/>
<FormControlLabel
value="starships"
control={<Radio />}
label="Starships"
checked={isButtonSelected('starships')}
onChange={handleChange}
/>
<FormControlLabel
value="vehicles"
control={<Radio />}
label="Vehicles"
checked={isButtonSelected('vehicles')}
onChange={handleChange}
/>
</RadioGroup>
</FormControl>
</Container>
);
};
export default ChooseOption;
const Container = styled.div`
text-align: center;
.radio-group {
width: 85%;
margin: auto;
color: white;
}
.MuiFormControlLabel-root {
display: grid;
margin: 1rem 1.5rem;
.MuiButtonBase-root {
background-color: #000;
}
}
`;
将单选按钮的状态保留在 2 个位置可能会有点混乱,因此请考虑将状态管理完全移到内部SearchItem
推荐阅读
- discord.js - 如何创建只有给定角色才能看到的频道?
- java - 在 WebView 中下载文件后如何使应用程序不显示“无 Internet 连接”消息?
- c# - IText:无法设置 PdfSignatureAppearance 的 СryptoDictionary 属性
- google-apps-script - 使用 Google Apps 脚本创建 Strava Webhook 订阅时出现问题
- javascript - 文本内容未在反应中更新
- java - 从看不见的邮件中下载附件
- c# - 在 C# GDI 中的鼠标位置射击球
- ocaml - 定义一个基于引用返回另一个函数的函数
- python - 如何检查 css_selector 当前是否存在于 selenium python 中
- angular - 如何让多个自动完成元素的选择相互独立