How can I display the result of the child component in the parent component?

Viewed 59

my application consists of a filter select by provinces, the filter is a modal that shows me the result in the filter component (child), I would like to show the result in the parent not in the filter modal. I do not know what to pass to the parent to show the result or how to show it on the screen.

///parent component

import React, { useState, useEffect } from 'react'
import { useDispatch } from "react-redux";
import { getClinic } from '../../api/drupalAPI'
import {Clinic} from '@icofcv/common';
import { selectClinics } from '../../actions/detailClinics'
import { useNavigate } from "react-router-dom";
import contentUtils from '../../lib/contentUtils'
import { SearchFilterClinics } from './SearchFilterClinics'
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';


    const ClinicList = () => {

    const [clinicList, setClinicList] = useState<Clinic[]>([]);
    const [clinicListFiltered, setClinicListFiltered] = useState<Clinic[]>([]);
    const [searchClinic, setSearchClinic] = useState("");
    const dispatch = useDispatch();
    const navigate = useNavigate(); 
    ///modal control

    const [isOpen, setIsOpen] = useState(false);
    const openModal = () => setIsOpen(true);
    const closeModal = () => setIsOpen(false);
    
    console.log(searchClinic);
    
    const fetchClinicList = async () => {
        getClinic().then((response)=>{
            console.log(response)
            setClinicList(response);
            setClinicListFiltered(response)
        }).catch ( (error)  => {
            console.error(error);
            throw error;
        });
    }

    const handleChange=e=>{
        setSearchClinic(e.target.value);
        filter(e.target.value);
      }
      
      const filter=(termSearch)=>{
        const resultSearch= clinicList.filter((element)=>{
          if(element.title.toString().toLowerCase().includes(termSearch.toLowerCase())
          ){
            return element;
          }
        });
        setClinicListFiltered(resultSearch);
      }

      function handleAddToDetail(clinic) {
        dispatch(selectClinics(clinic));
        navigate('clinicdetail');
      }

      function goToPageSearchFilterClinics() {
        navigate('filterclinics');
    } 
  

    useEffect (() => {
        fetchClinicList();  
    }, []);

    return(
            <>
                <div style={{display: 'flex'}}>
                    <div style={{width:'5rem'}}>
                        {/* <button  onClick={() => goToPageSearchFilterClinics()}>filtro</button>  */}
                        <button  onClick={openModal}>filtro</button>  
                    </div>
                    < SearchFilterClinics  isOpen={isOpen} closeModal={closeModal} clinicFilter={clinicFilter}></SearchFilterClinics>

                    <Form className="d-flex">
                        <Form.Control
                        type="search"
                        value={searchClinic}
                        placeholder="Search"
                        className="me-2"
                        aria-label="Search"
                        onChange={handleChange}
                        />
                    </Form>
                    
              </div>
                <div className="content-cliniclist">
                    
                    {
                         clinicListFiltered.map((clinic) => (
                             <div style={{marginBottom: '3rem'}}>
                                <button
                                    type="button"
                                    onClick={() => handleAddToDetail(clinic)}
                                    style={{all: 'unset'}}
                                    >
                                    
                                    <div>
                                        {/* <img src={ contentUtils.getLargeImageUrl(clinic.logoWidth )} alt="#"></img> */}
                                        <div>{clinic.title}</div>
                                        <div>{clinic.propsPhone}</div>
                                        <div>{clinic.mobile}</div>
                                        <div>{clinic.email}</div>
                                        <div>{clinic.registry}</div>
                                    </div>
                                </button>
                             </div>
                        ))
                    }
                                
             </div>
            </>  
    )
}

 export default ClinicList; 


////child component

import React, { useState, useEffect } from 'react'
import Select, { SingleValue } from 'react-select'
import { getClinic } from '../../api/drupalAPI'
import {Clinic} from '@icofcv/common';
import "./Modal.css";

interface Props {
    isOpen: boolean,
    clinicFilter: String,
    closeModal: () => void
}


export const SearchFilterClinics : React.FC<Props> = ({ children, isOpen, closeModal, clinicFilter }) => {

         ////filter

         type OptionType = {
            value: string;
            label: string;
          };
    
          
            const provincesList: OptionType[] = [
                { value: 'Todos', label: 'Todos' },
                { value: 'Valencia', label: 'Valencia' },
                { value: 'Castellon', label: 'Castellon' },
                { value: 'Alicante', label: 'Alicante' },
               
            ]

    const [clinicList, setClinicList] = useState<Clinic[]>([]);
    const [clinicListFilteredSelect, setClinicListFilteredSelect] = useState<Clinic[]>([]);
    const [filterSelectClinic, setFilterSelectClinic] = useState<SingleValue<OptionType>>(provincesList[0]);

    const handleChangeSelect = async (provinceList: SingleValue<OptionType>) => {
        getClinic().then((response) => {
            setClinicList(response);
            setClinicListFilteredSelect(response)
            setFilterSelectClinic(provinceList);
            filterSelect(provinceList );
          }).catch ((error) => {
            console.error(error);
            throw error;
        });         
      }

       
      const filterSelect=(termSearch)=>{
        const resultFilterSelect = clinicList.filter((element) => {
          if(element.province?.toString().toLowerCase().includes(termSearch.value.toLowerCase() )
        
          ){
            return element;
          }
        });
        setClinicListFilteredSelect(resultFilterSelect);
      }

      const handleModalContainerClick = (e) => e.stopPropagation();

   

    return  (
                <>
                     <div className={`modal ${isOpen && "is-open"}`} onClick={closeModal}>
                         <div className="modal-container" onClick={handleModalContainerClick}>
                            <button className="modal-close" onClick={closeModal}>x</button>
                            {children}
                           
                            <div>
                                <h1>Encuentra tu clínica</h1>
                            </div>
                                 <div>
                                    <form>
                                        
                                        <label>Provincia</label>
                                            <Select 
                                                defaultValue={filterSelectClinic}
                                                options={provincesList}
                                                onChange={handleChangeSelect}
                                                />

                                       </form>


                                { 
                                  
                                    clinicListFilteredSelect.map((clinicFilter) => (
                                        <div>
                                            <div>{clinicFilter.title}</div>
                                            <div>{clinicFilter.propsPhone}</div>
                                            <div>{clinicFilter.mobile}</div>
                                            <div>{clinicFilter.email}</div>
                                            <div>{clinicFilter.province} </div>
                                            <div>{clinicFilter.registry}</div>
                                        </div>
                                    ))
                                }
                            </div>
                    </div>
                </div>

                          
                </>
            )
}
1 Answers

You need to pass a callback function to the parent and set the state value in the parent, not in the child. (This is known as lifting state up.)

In your case this would involve moving

const [filterSelectClinic, setFilterSelectClinic] = useState<SingleValue<OptionType>>(provincesList[0]);

Into the parent component. Then passing the setFilterSelectClinic function into the child component.

<SearchFilterClinics setFilterSelectClinic={(value) => setFilterSelectClinic(value)} isOpen={isOpen} closeModal={closeModal} clinicFilter={clinicFilter}/>

The value (within the parenthesis) is being passed up by the child component. This is the value you set here:

getClinic().then((response) => {
 ...
 // this is the function we pass in from the parent. It set's the value
 // of the callback function to provinceList
    setFilterSelectClinic(provinceList);
 ...

We then setFilterSelectClinic to that value. Meaning filterSelectClinic now has the value passed up in the callback.

Related