我是React、JS、JSX的新手。
似乎setNewWeather没有正确地更新天气状态,也就是说,它被定义为初始值,但后来又变成了undefined。
因为如果它更新了,应该会引起重新渲染;我已经查看了很多关于此的帖子,但它们建议等待异步数据操作,但按照我的理解,使用'.then'方法天然地实现了这一点?或者这是涉及到setNewWeather语法的不同问题,比如需要在内部使用一个函数而不仅仅是一个字符串来更新状态?
我的代码:
import React, { useState, useEffect } from 'react'
import axios from 'axios'
const Header = ({ text }) => <h1>{text}</h1>
const Header3 = ({ text }) => <h3>{text}</h3>
const Image = ({ source, alttext }) => <img src={source} alt={alttext} />
const Button = ({ onClick, text }) => (<button onClick={onClick}>{text}</button>)
const ListItem = ({ item }) => <li>{item}</li>
const List = ({ title, stuff }) => {
return(
<>
< Header3 text={title} />
<ul>
{stuff.map((item, index) => < ListItem key={index} item={item} />)}
</ul>
</>)}
const Search = ({ text, value, onChange }) => {
return (
<>
{text}
<input value={value} onChange={onChange} />
</>)}
const CountryMany = ({ country, handleClick }) => {
return (
<>
<li>{country.name}</li>
< Button onClick={handleClick(country.name)} text='Show' />
</>)}
const CountryFound = ({ country, api_key, handleWeather, newWeather }) => {
const countryFound = country[0]
const params = {
access_key: api_key,
query: countryFound.capital
}
useEffect(() => {
axios.get('http://api.weatherstack.com/current', {params})
.then(response => {
console.log('RESPONSE', response.data)
handleWeather({ is: 'weather', data: response.data })
console.log(newWeather)
})},
[params, newWeather, handleWeather])
console.log('yo')
console.log(newWeather)
const languages = countryFound.languages.map(lang => lang.name)
return (
<>
< Header text={countryFound.name} />
<p>Capital: {countryFound.capital}</p>
<p>Population: {countryFound.population}</p>
< List title='Languages' stuff={languages} />
< Header3 text='Flag' />
< Image source={countryFound.flag} alttext='flag' />
< Header3 text='Weather' />
<ul>
<li>Temperature: {newWeather}</li>
<li> Image source= alttext=weather </li>
</ul></>)}
const Countries = (props) => {
console.log('COUNTRIES PROPS', props)
console.log('WEATHER', props.newWeather)
const countries = props.countries
const foundCountries = countries.filter(country =>
country.name.toLowerCase().includes(props.newSearch.toLowerCase()))
if (foundCountries.length > 10 ) {
return (<p>Too Many Matches, Keep Typing!</p>)}
if (foundCountries.length > 1) {
return (
<ul>
{foundCountries.map(country =>
< CountryMany key={country.population} country={country} handleClick={props.handleClick} />)}
</ul>)}
if (foundCountries.length === 1) {
return (
<>
<CountryFound api_key={props.a_k1} country={foundCountries}
handleWeather={props.handleWeather} weather={props.newWeather} />
</>)}
return (<></>)}
const App = () => {
const api_key = process.env.REACT_APP_API_KEY
const [ countries, setCountries ] = useState([])
const [ newSearch, setNewSearch ] = useState('')
const [ newWeather, setWeather ] = useState({ is: 'no ewather' })
const handleWeather = ( is, data ) => () => {
setWeather( is, data )
console.log('HEY HANDLEWEATHER', newWeather)}
useEffect(() => {
axios
.get('https://restcountries.eu/rest/v2/all')
.then(response => {
setCountries(response.data)
})}, [])
const handleClick = (value) => () => {
setNewSearch(value)}
const handleSearch = (event) => {
setNewSearch(event.target.value)}
return (
<div>
< Search text='Find A Country: ' value={newSearch} onChange={handleSearch}/>
< Countries countries={countries}
a_k1={api_key}
handleWeather={handleWeather}
handleClick={handleClick}
newSearch={newSearch}
newWeather={newWeather}
/>
</div>)}
export default App
/*
const Weather = ({ weather }) => {
return (
<>
< Header3 text='Weather' />
<ul>
<li>Temperature: weather.temperature</li>
<li> Image source= alttext=weather </li>
</ul>
</>)}
*/
谢谢!
编辑:状态正在更新,但只通过形成无限循环来实现:
import React, { useState, useEffect } from 'react'
import axios from 'axios'
const Header = ({ text }) => <h1>{text}</h1>
const Header3 = ({ text }) => <h3>{text}</h3>
const Image = ({ source, alttext }) => <img src={source} alt={alttext} />
const Button = ({ onClick, text }) => (<button onClick={onClick}>{text}</button>)
const ListItem = ({ item }) => <li>{item}</li>
const List = ({ title, stuff }) => {
return(
<>
< Header3 text={title} />
<ul>
{stuff.map((item, index) => < ListItem key={index} item={item} />)}
</ul>
</>)}
const Search = ({ text, value, onChange }) => {
return (
<>
{text}
<input value={value} onChange={onChange} />
</>)}
const CountryMany = ({ country, handleClick }) => {
return (
<>
<li>{country.name}</li>
< Button onClick={handleClick(country.name)} text='Show' />
</>)}
const CountryFound = ({ countryFound, api_key, handleWeather, newWeather }) => {
const params = { access_key: api_key, query: countryFound.capital }
useEffect(() => {
axios.get('http://api.weatherstack.com/current', {params})
.then(response => {
console.log('RESPONSE', response.data)
handleWeather(response.data)
})})
const languages = countryFound.languages.map(lang => lang.name)
if (newWeather.length > 0 ){
return (
<>
< Header text={countryFound.name} />
<p>Capital: {countryFound.capital}</p>
<p>Population: {countryFound.population}</p>
< List title='Languages' stuff={languages} />
< Header3 text='Flag' />
< Image source={countryFound.flag} alttext='flag' />
< Header3 text='Weather' />
<ul>
<li>Temperature/rendering {newWeather}</li>
<li> Image source= alttext=weather </li>
</ul></>)}
return (
<></>
)}
const Countries = (props) => {
console.log('COUNTRIES PROPS', props)
console.log('WEATHER', props.newWeather)
const foundCountries = props.countries.filter(country =>
country.name.toLowerCase().includes(props.newSearch.toLowerCase()))
if (foundCountries.length > 10 ) {
return (<p>Too Many Matches, Keep Typing!</p>)}
if (foundCountries.length > 1) {
return (
<ul>
{foundCountries.map(country =>
< CountryMany key={country.population} country={country} handleClick={props.handleClick} />)}
</ul>)}
if (foundCountries.length === 1) {
return (
<>
<CountryFound api_key={props.a_k1} countryFound={foundCountries[0]}
handleWeather={props.handleWeather} newWeather={props.newWeather} />
</>)}
return (<></>)}
const App = () => {
const api_key = process.env.REACT_APP_API_KEY
const [ countries, setCountries ] = useState([])
const [ newSearch, setNewSearch ] = useState('af')
const [ newWeather, setWeather ] = useState([])
const handleClick = (value) => () => {
setNewSearch(value)}
const handleSearch = (event) => {
setNewSearch(event.target.value)}
useEffect(() => {
axios
.get('https://restcountries.eu/rest/v2/all')
.then(response => {
setCountries(response.data)
})}, [])
return (
<div>
< Search text='Find A Country: ' value={newSearch} onChange={handleSearch}/>
< Countries countries={countries}
a_k1={api_key}
handleWeather={setWeather}
handleClick={handleClick}
newSearch={newSearch}
newWeather={newWeather}
/>
</div>)}
export default App
编辑最终版:已解决!
下面的标记解决了最初的问题,但生成了一个无限循环。整个问题已经得到纠正,尽管我还不太理解这些更改是如何实现的。
import React, { useState, useEffect } from 'react'
import axios from 'axios'
const Header = ({ text }) => <h1>{text}</h1>
const Header3 = ({ text }) => <h3>{text}</h3>
const Image = ({ source, alttext }) => <img src={source} alt={alttext} />
const Button = ({ onClick, text }) => (<button onClick={onClick}>{text}</button>)
const ListItem = ({ item }) => <li>{item}</li>
const List = ({ title, stuff }) => {
return(
<>
< Header3 text={title} />
<ul>
{stuff.map((item, index) => < ListItem key={index} item={item} />)}
</ul>
</>)}
const Search = ({ text, value, onChange }) => {
return (
<>
{text}
<input value={value} onChange={onChange} />
</>)}
const CountryMany = ({ country, handleClick }) => {
return (
<>
<li>{country.name}</li>
< Button onClick={handleClick(country.name)} text='Show' />
</>)}
const CountryFound = ({ countryFound, api_key, handleWeather, newWeather }) => {
useEffect(() => {
axios.get(`https://api.weatherbit.io/v2.0/current?city=${countryFound.capital}&key=${api_key}`)
.then(response => {
handleWeather(response.data.data[0])
})})
const languages = countryFound.languages.map(lang => lang.name)
if (newWeather > '' ) {
const capital = countryFound.capital
const weatherTitle = `Weather in: ${capital}`
const weatherImage = `https://www.weatherbit.io/static/img/icons/${newWeather.weather.icon}.png`
return (
<>
< Header text={countryFound.name} />
<p>Capital: {capital}</p>
<p>Population: {countryFound.population}</p>
< List title='Languages' stuff={languages} />
< Header3 text='Flag' />
< Image source={countryFound.flag} alttext='flag' />
< Header3 text={weatherTitle} />
< Image source={weatherImage} alttext='weather' />
<ul>
<li>Temperature: {newWeather.temp} degrees Celsius</li>
<li>Wind: {newWeather.wind_spd} mph towards {newWeather.wind_cdir}</li>
</ul></>)}
return (<><p>Loading...</p></>)}
const Countries = (props) => {
const foundCountries = props.countries.filter(country =>
country.name.toLowerCase().includes(props.newSearch.toLowerCase()))
if (foundCountries.length > 10 ) {
return (<p>Too Many Matches, Keep Typing!</p>)}
if (foundCountries.length > 1) {
return (
<ul>
{foundCountries.map(country =>
< CountryMany key={country.population}
country={country}
handleClick={props.handleClick} />)}
</ul>)}
if (foundCountries.length === 1) {
return (<>
<CountryFound api_key={props.a_k1} countryFound={foundCountries[0]}
handleWeather={props.handleWeather} newWeather={props.newWeather} />
</>)}
return (<></>)}
const App = () => {
const api_key = process.env.REACT_APP_API_KEY
const [ countries, setCountries ] = useState([])
const [ newSearch, setNewSearch ] = useState('af')
const [ newWeather, setWeather ] = useState('')
const handleClick = (value) => () => {
setNewSearch(value)}
const handleSearch = (event) => {
setNewSearch(event.target.value)}
useEffect(() => {
axios
.get('https://restcountries.eu/rest/v2/all')
.then(response => {
setCountries(response.data)
})}, [])
return (
<div>
< Search text='Find A Country: ' value={newSearch} onChange={handleSearch}/>
< Countries countries={countries}
a_k1={api_key}
handleWeather={setWeather}
handleClick={handleClick}
newSearch={newSearch}
newWeather={newWeather}
/>
</div>)}
export default App
setWeather({is: data} )
- Sarun UK