简体   繁体   中英

How to display JSX returned from other function inside return?

I'm trying to build a weather application using openweathermap api. As you can see below in the code, I use a boolean state to check when the form is summitted so I can pass that value to the <Result> component(which I checked with hard code and it works). I want the function changeCity (in the App) to return the <Result> component with the value of city passed and in the same time to change the cityEmpty state. But there I got the problem when I pass that in the return() {(cityEmpty) ? changeCity() : null} {(cityEmpty) ? changeCity() : null}

import React, {useState} from 'react';
import Result from "./components/Result";
import Search from "./components/Search";
import './App.css';

function App() {
    
  const [city, setCity] = useState ("");
  const [cityEmpty, setCityEmpty] = useState(false);
  
  const changeCity = () => {
    setCityEmpty(false);
    return (<Result city={city}/>);
  }

  return (
    <div className="App">
      <Search city={city} setCity={setCity} cityEmpty={cityEmpty} setCityEmpty={setCityEmpty} 
      />
      {(cityEmpty) ? changeCity() : null}
      
    </div>
  );
}

export default App;
import React from "react"

function Search({city, setCity, cityEmpty, setCityEmpty}){

  const handleInputChange = (e) => {
    setCity(e.target.value);
  }

  const handleSumbit = (e) => {
    e.preventDefault();
    console.log(cityEmpty);
    setCityEmpty(true);
    console.log(cityEmpty);
    setCity("");
  }

  return(
  <div>
    <form onSubmit={handleSumbit}>
      <input
      type="text"
      placeholder="Insert city"
      value={city}
      onChange = {handleInputChange}
      >
      </input>
    </form>
  </div>
);

}

export default Search

You can't call a state update inside the render of a component. Remember that whenever state is updated, it will re render the component. This will cause an infinite loop in your component.

  1. Component renders
  2. changeCity is called
  3. Inside changeCity , setCityEmpty is called
  4. Go back to step 1 for rendering.

Instead, consider checking if city is empty in your handleInputChange and calling setCityEmpty inside that function.

EDIT: To clarify a function that returns a component is completely fine, this is all components are really. Functions (or in previous react versions: classes) returning other components.

you don't have to return JSX from function. In your case it is pretty straightforward to use.

import React, {useState} from 'react';
import Result from "./components/Result";
import Search from "./components/Search";
import './App.css';

function App() {
    
  const [city, setCity] = useState ("");
  const [cityEmpty, setCityEmpty] = useState(false);
  

  return (
    <div className="App">
      <Search city={city} setCity={setCity} cityEmpty={cityEmpty} setCityEmpty={setCityEmpty} 
      />
      {cityEmpty && <Result city={city}/>}
      
    </div>
  );
}

export default App;


import React from "react"

function Search({city, setCity, cityEmpty, setCityEmpty}){

  const handleInputChange = (e) => {
    setCity(e.target.value);
  }

  const handleSumbit = (e) => {
    e.preventDefault();
    console.log(cityEmpty);
    setCityEmpty(true);
    console.log(cityEmpty);
    setCity("");
  }

  return(
  <div>
    <form onSubmit={handleSumbit}>
      <input
      type="text"
      placeholder="Insert city"
      value={city}
      onChange = {handleInputChange}
      >
      </input>
    </form>
  </div>
);

}

export default Search

Not sure what the problem you're seeing is but I noticed you're setting state inside of a render function, which is a bad pattern. Any state changes will trigger a re-rendering of the component and if you set state within a render function then you'd have an infinite loop of re-renderings (but.

Try removing setCityEmpty(false) in changeCity .

const changeCity = () => {
  return (<Result city={city}/>);
}

So how would you update cityEmpty? It's not clear what the end goal is here. With more info, we can find a better implementation.

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