首页 > 解决方案 > 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;
    }
`;

标签: javascriptreactjsapimaterial-uiradio-button

解决方案


您将 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


推荐阅读