I was looking over React: Reverse data Flow, to update foodObj
, input
and buttonClicked
declared in Main.js
(Parent Component) using the child component <SearchAndSuggestion>
. Here are the two files.
my-app/app/page.js
(Parent File)-
'use client'
import React, {useState} from 'react'
import FoodList from "./today_page/list/page";
import NutritionTable from "./today_page/nutrition_table/page";
import SearchAndSuggestion from "./today_page/search_and_suggestions/page";
export default function Home() {
const [foodObj, setFoodObj] = useState({});
const [input, setInput] = useState("");
const [buttonClicked, setButtonClicked] = useState(false);
const buttonF = (value) => {
setButtonClicked(value)
}
const inputF = (value) => {
setInput(value)
}
const foodObjF = (value) => {
setFoodObj(value)
}
return (
<main className="flex flex-row overflow:hidden items-center justify-between p-24">
...
<div className='flex flex-col m-4 border-blue-600'>
...
{/* right side upper half*/}
<SearchAndSuggestion foodObjF={foodObjF} inputF = {inputF} buttonF ={buttonF}/>
...
</div>
<p>{foodObj + ", " + input + ", " + buttonClicked}</p>
</main>
)
}
my-app/app/today_page/seaerch_and_suggestion/page.js
(Child Component) –
'use client'
import { useEffect } from "react"
const SearchAndSuggestion = ({foodObjF, inputF, buttonF}) => {
let query = " "
const updateObj = (obj, query) => {
if(obj && typeof obj === 'object'){
if(!obj.hasOwnProperty(query)){
obj[query] = 1
}else{
obj[query]++
}
}
return obj
}
const handleClick = () => {
if(query != " "){
inputF(query)
foodObjF(prevObj => updateObj(prevObj, query))
buttonF(true)
query = " "
document.getElementById('myInput').value = ''
}else{
console.log("Failed")
}
}
return (
// Search bar, button with suggestion box
<div className='flex flex-col flex-wrap box-border bg-gray-500 rounded-2xl border-gray-950 border-r-blue-600'>
<form className='flex flex-row'>
<input
id = "myInput"
className='m-2 w-120 h-8 rounded-2xl'
onChange = {(e) => {
query = e.target.value
}}
/>
<button
className='w-20 h-8 bg-white m-2 rounded-2xl'
type='button'
onClick = {() => handleClick}
>
Find
</button>
</form>
<div className='box-border h-48 w-144 m-2 bg-gray-300 border-1 rounded-2xl bg-grey-200'>
</div>
</div>
)
}
export default SearchAndSuggestion
The problem is that whenever I enter something in the input made inside <SearchAndSuggestion>
, it doesn’t change <p>{foodObj + ", " + input + ", " + buttonClicked}</p>
written in Parent component file. I am not sure where the problem exist. Could someone point it out?
Thanks!
2
Answers
Firstly, in the button’s click handler, you’re not calling the
handleClick
function, you’re just returning it.Should look like this:
or better still pass is directly to the
onClick
handler:Secondly, you can’t set a variable in react the way you did in the input’s
onChange
handler.You have to make
query
a state and make the input controlled.Like so:
You’re first using a local variable and not state when you’re changing
query
, so you will not get a re-render since react will only re-render a component when state(s) change. I think it may be best to understand controlled inputs in react (simply, you have to use state var as the value of the input and on the specific event, update that state).In your case, you could send both the input (state) and the setState fn for that input.
seems like another commenter also mentioned it as well.