0

REACT.js:

Let say I have a home page with a search bar, and the search bar is a separate component file i'm calling.

The search bar file contains the useState, set to whatever the user selects. How do I pull that state from the search bar and give it to the original home page that SearchBar is called in?

The SearchBar Code might look something like this..

import React, { useEffect, useState } from 'react'
import {DropdownButton, Dropdown} from 'react-bootstrap';
import axios from 'axios';
const StateSearch = () =>{
    const [states, setStates] = useState([])
    const [ stateChoice, setStateChoice] = useState("")

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

    const getStates = async () => {
        let response = await axios.get('/states')
        setStates(response.data)
    }

    const populateDropdown = () => {
         return states.map((s)=>{
            return (
                 <Dropdown.Item as="button" value={s.name}>{s.name}</Dropdown.Item>
             )
         })
    }
    const handleSubmit = (value) => {
        setStateChoice(value);
    }
    return (
        <div>
            <DropdownButton
             onClick={(e) => handleSubmit(e.target.value)}
             id="state-dropdown-menu" 
             title="States"
             >
                {populateDropdown()}
            </DropdownButton>
        </div>
    )
}

export default StateSearch; 

and the home page looks like this

import React, { useContext, useState } from 'react'
import RenderJson from '../components/RenderJson';
import StateSearch from '../components/StateSearch';
import { AuthContext } from '../providers/AuthProvider';

const Home =  () => {
  const [stateChoice, setStateChoice] = useState('')
  const auth = useContext(AuthContext)
  console.log(stateChoice)
  return(
    <div>
      <h1>Welcome!</h1>
      <h2> Hey there! Glad to see you. Please login to save a route to your prefered locations, or use the finder below to search for your State</h2>
      <StateSearch stateChoice={stateChoice} />
    </div>
  )
};

export default Home;

As you can see, these are two separate files, how do i send the selection the user makes on the search bar as props to the original home page? (or send the state, either one)

Nisharg Shah
  • 16,638
  • 10
  • 62
  • 73
DaPlank
  • 21
  • 1
  • 3

4 Answers4

1

You just need to pass one callback into your child.

Homepage

<StateSearch stateChoice={stateChoice} sendSearchResult={value => {
   // Your Selected value
}} />

Search bar

const StateSearch = ({ sendSearchResult }) => {

..... // Remaining Code

const handleSubmit = (value) => {
   setStateChoice(value);
   sendSearchResult(value);
}
Nisharg Shah
  • 16,638
  • 10
  • 62
  • 73
1

You can lift the state up with function you pass via props.

const Home = () => {

  const getChoice = (choice) => {
    console.log(choice);
  } 

  return <StateSearch stateChoice={stateChoice} giveChoice={getChoice} />
}
const StateSearch = (props) => {
  const handleSubmit = (value) => {
    props.giveChoice(value);
  }

  // Remaining code ...
}

Actually there is no need to have stateChoice state in StateSearch component if you are just sending the value up.

  • Hey thanks! The other posts worked too but yours was the most simple and easiest to understand answer. Thank you. – DaPlank Jul 10 '22 at 00:59
0

Just pass a setState to component parent component:

const [state, setState] = useState({
   selectedItem: ''
})

<StateSearch state={state} setState={setState} />

change parent state from child component:

const StateSearch = ({ state, setState }) => {

const handleStateChange = (args) => setState({…state, selectedItem:args})

return (...
    <button onClick={() => handleStateChange("myItem")}/>
...)
}
antokhio
  • 1,497
  • 2
  • 11
  • 16
  • Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Mark Rotteveel Jul 11 '22 at 08:34
0

Hello and welcome to StackOverflow. I'd recommend using the below structure for an autocomplete search bar. There should be a stateless autocomplete UI component. It should be wrapped into a container that handles the search logic. And finally, pass the value to its parent when the user selects one.

// import { useState, useEffect } from 'react' --> with babel import
const { useState, useEffect } = React  // --> with inline script tag



// Autocomplete.jsx

const Autocomplete = ({ onSearch, searchValue, onSelect, suggestionList }) => {

  return (
    <div>
      <input
        placeholder="Search!"
        value={searchValue}
        onChange={({target: { value }}) => onSearch(value)}
      />
      <select
        value="DEFAULT"
        disabled={!suggestionList.length}
        onChange={({target: {value}}) => onSelect(value)}
        >
        <option value="DEFAULT" disabled>Select!</option>
        {suggestionList.map(({ id, value }) => (
          <option key={id} value={value}>{value}</option>
        ))}
      </select>
    </div>
  )
}


// SearchBarContainer.jsx

const SearchBarContainer = ({ onSelect }) => {
  const [searchValue, setSearchValue] = useState('')
  const [suggestionList, setSuggestionList] = useState([])
  
  useEffect(() => {
    if (searchValue) {
      // some async logic that fetches suggestions based on the search value
      setSuggestionList([
        { id: 1, value: `${searchValue} foo` },
        { id: 2, value: `${searchValue} bar` },
      ])
    }
  }, [searchValue, setSuggestionList])
  
  return (
    <Autocomplete
      onSearch={setSearchValue}
      searchValue={searchValue}
      onSelect={onSelect}
      suggestionList={suggestionList}
    />
    )
}

// Home.jsx
  
const Home = ({ children }) => {
  const [result, setResult] = useState('')
  
  return (
    <div>
      <SearchBarContainer onSelect={setResult} />
      result: {result}
    </div>
  )
}

ReactDOM.render(<Home />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
gazdagergo
  • 6,187
  • 1
  • 31
  • 45