Search code examples
javascriptreactjsreact-component

React get selected value from child component combobox


Calling the child component, comboBox.

I am new in React and trying to save data from a child component but I am not receiving this value at the Parent component. I tryed some approaches with function at both components, but I just saw some examples using classes with 'this.[FUNCTION]' and I am not using function in this following code.

export default function PostApartment() {
  const [apartment_id, setApartmentId] = useState('');
  const [apartment_floor, setApartmentFloor] = useState('');
  const [apartment_size, setApartmentSize] = useState('');
  const [apartment_data, setApartmentData] = useState('');
  const [tower_data, setTowerData] = useState('');
  const classes = useStyles();

  const urlSearchApartment = 'http://localhost:' + config.port + '/apartment';

  const handleClick = (e) => setTowerData(e.target.value);
  console.log('tower_data - definition: ', tower_data);

  useEffect(() => {
    axios
      .get(`${urlSearchApartment}/`, {
        port: config.port,
      })
      .then((res) => {
        setApartmentData(res.data);
      })
      .catch((err) => {
        console.log(err);
      });
  }, [urlSearchApartment]);

  useEffect(() => {
    axios
      .get(urlSearchTower, {
        port: config.port,
      })
      .then((res) => {
        setTowerData(res.data);
      })
      .catch((err) => {
        console.log(err);
      });
  }, []);

  return (
    <div className={classes.formLayout}>      
        <Header titleHeader={'Cadastro de apartamentos'} />

        <Typography className={classes.marginAlignment} variant='h4'>
          Cadastrar a localização e tamanho dos apartamentos
        </Typography>
        <Typography
          className={classes.marginAlignment}
          color='textSecondary'
          variant='body2'
        >
          O objetivo organizar a destribuição dos apartamentos e o tamanho, para
          poder organizar as informações do condomínio.
        </Typography>
        <Divider variant='middle' />

        <form>
          <FormControl>
            <Grid
              container
              spacing={0}
              direction='row'
              alignItems='flex-end'
              className={classes.marginAlignment}
            >

              {apartment_data ? (
                <ComboBox
                  field='tower_id'
                  data={tower_data}                  
                  description='Número do bloco'
                  onChange={handleClick}
                />
              ) : (
                ''
              )}
              <TextField
                required
                className={classes.marginRight}
                id='aparmentId'
                name='aparmentId'
                label='Número do apartamento'
                type='text'
                onChange={(e) => setApartmentId(e.target.value)}
                helperText='Identificador do apartamento'
              />
              <TextField
                className={(classes.marginRight, classes.marginAlignment)}
                id='apartmentFloor'
                name='apartmentFloor'
                label='Andar do apartamento'
                type='text'
                onChange={(e) => setApartmentFloor(e.target.value)}
                helperText='Exemplo:Informar o andar do apartamento'
              />
              <div className={(classes.marginRight, classes.marginAlignment)}>
                {apartment_data ? (
                  <ComboBox
                    field='apartment_size'
                    data={apartment_data}
                    description='Tamanho do apartamento'
                    onClick={(e) => setApartmentSize(e.target.value)}
                  />
                ) : (
                  ''
                )}
              </div>
              <div className={(classes.marginRight, classes.marginAlignment)}>
                {apartment_data ? (
                  <ComboBox
                    field='apartment_parking_id'
                    data={apartment_data}
                    description='Número da vaga que o apartamento utiliza'
                  />
                ) : (
                  ''
                )}
              </div>
            </Grid>
            <Grid container spacing={0} direction='row'>
              <Router forceRefresh={true}>
                <Switch>
                  <Route>
                    <Link to='/apartment'>
                      <Grid
                        item
                        xs={12}
                        sm={6}
                        className={classes.marginAlignment}
                      >
                        <Button
                          type='submit'
                          variant='contained'
                          color='primary'
                          size='large'
                          onClick={() => {
                            axios
                              .post(
                                `http://${config.host}:${config.port}/apartment`,
                                {
                                  apartment_id: apartment_id,
                                  apartment_block_id: tower_data,
                                  apartment_block_name:
                                    apartment_data.apartment_block_name,
                                  apartment_floor: apartment_floor,
                                  apartment_size: apartment_size,
                                  apartment_parking_id:
                                    apartment_data.apartment_parking_id,
                                },
                              )
                              .then(function (response) {
                                console.log(response);
                              })
                              .catch(function (error) {
                                console.log(error);
                              });
                          }}
                        >
                          Cadastrar
                        </Button>
                      </Grid>
                    </Link>

                    <Grid
                      item
                      xs={12}
                      sm={6}
                      className={classes.marginAlignment}
                    >
                      <Button
                        variant='contained'
                        color='secondary'
                        size='large'
                      >
                        Sair
                      </Button>
                    </Grid>
                  </Route>
                </Switch>
              </Router>
            </Grid>
          </FormControl>
        </form>
    </div>
  );
}

The child component structure.

import React, { useState } from 'react';
import FormHelperText from '@material-ui/core/FormHelperText';
import { makeStyles } from '@material-ui/core/styles';


export default function ComboBox(props) {
  const classes = useStyles();

  function renderOption() {
    return props.data
      ? props.data.map((dataDescription, key) => {
          return <option key={key}>{dataDescription[props.field]}</option>;
        })
      : '';
  }
  const [selectedValue, setSelectedValue] = useState('');
  const handleClick = (e) => setSelectedValue(e.target.value);
  console.log('selectedValue: ', selectedValue);

  return (
    <div className={classes.marginRight} onChange={handleClick}>
      <div>
        <select className={classes.input}>
          <option value=''></option>
          {renderOption()}
        </select>
      </div>
      <FormHelperText>{props.description}</FormHelperText>
    </div>
  );
}

I can find the selected value, but I would like to manipulate this value at the Parent component, to send all the payload to the API. Can someone help on it and suggest more architectural approach for this code?


Solution

  • **

    Parent component

    **

    I am passing the onChange event to the child component.

    <ComboBox
     field='apartment_size'
     data={apartment_data}
     description='Tamanho do apartamento'
     onChange={(value) => setApartmentSize(value)}
    />
    

    **

    Child component (ComboBox)

    **

    I have included the props.onChange at the component

    <div className={classes.marginRight} onChange={(event) => props.onChange(event.target.value)}>
    

    The Parent component receive the event and set it to a state.