简体   繁体   中英

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, eg 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;
    }
`;

You're passing an onChange handler to your ChooseOption component but are never calling it. You can either hold the state of the radio button inside your SearchItem component (as you already have a state object for it (selected), or you can add a useEffect hook inside ChooseOption that calls onChange every time your selected state is updated inside there (or better yet in your handleChange function:

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;
        }
    }
`;

Holding your state of the radio buttons in 2 places might be a bit confusing, so consider moving the state management entirely inside SearchItem

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM