【发布时间】:2021-01-17 12:27:57
【问题描述】:
我是 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
【问题讨论】:
-
在状态管理方面,我个人认为更安全的是“reducer”工作流程,例如 Redux 或 -my preference-useReducer,它是 React 本身的一部分。绝对值得一读:reactjs.org/docs/hooks-reference.html#usereducer
-
试试这个 --
setWeather({is: data} ) -
谢谢臭氧,会的。 @Saran:谢谢,是的,我明白了。没有解决更大的问题,但这是一回事!
标签: reactjs axios setstate use-effect rerender