gpt4 book ai didi

javascript - 重新渲染组件不会更新功能组件内的对象

转载 作者:行者123 更新时间:2023-12-03 00:36:48 27 4
gpt4 key购买 nike

根据天气情况,应该显示某种类型的图标。

在我的Weather 组件中,我创建了一个包含所有相关图标的对象。我这样做了,而不是将其添加到 state 中,因为根据 React:

Can you compute it based on any other state or props in your component? If so, it isn’t state.

图标可以根据this.currentWeather.main的值计算出来。

第一次运行时一切正常,但如果您更改城市(更改为具有不同天气类型的城市),图标将保持不变。我不明白为什么。 (即,尝试使用美国塔斯廷 ---> 美国罗切斯特)

我尝试了 console.log(currentIcon),并且获得了一个符号对象,并且在其中它具有正确的属性值,但无法正确显示。

我的理解是,当状态更新时(通过您第二次进入另一个城市和国家/地区),Weather 组件应该重新渲染,并且 return 语句应该重新运行,我相信它确实做到了。

只是不确定为什么 return 语句中的 {currentIcon} 没有反射(reflect)该更改。

我很想知道答案,但更重要的是,我很想知道为什么显示没有更新。

const root = document.querySelector('.root');

class App extends React.Component {
constructor(props) {
super(props);
this.state = {
unit: '',
currentWeather: {
main: '',
desc: '',
temp: '',
}
}

this.getWeather = this.getWeather.bind(this);
this.unitHandler = this.unitHandler.bind(this);
}

getWeather(e) {
e.preventDefault();
const city = e.target.elements.city.value;
const country = e.target.elements.country.value;
const appID = 'bf6cdb2b4f3c1293c29610bd1d54512b';

const currentWeatherURL = `https://api.openweathermap.org/data/2.5/weather?q=${city},${country}&units=imperial&APPID=${appID}`;
const forecastURL = `https://api.openweathermap.org/data/2.5/forecast?q=${city},${country}&units=imperial&APPID=${appID}`;

//fetch CURRENT weather data ONLY
fetch(currentWeatherURL)
.then((response) => response.json())
.then((data) => {
this.setState({
unit: '°F',
currentWeather: {
main: data.weather[0].main,
desc: data.weather[0].description,
temp: data.main.temp,
}
});
})
.catch(() => {console.log('something went wrong, but we caught the error')});
}

unitHandler(e) {
function convertToCelsius(fahrenheit) {
return ((fahrenheit-32)*5/9)
}

function convertToFahrenheit(celsius) {
return ((celsius*9/5) + 32)
}

//if fahrenheit is checked
if(e.target.value === 'fahrenheit') {
const fahrenheitTemp = convertToFahrenheit(this.state.currentWeather.temp);
this.setState(prevState => ({
unit: '°F',
currentWeather: {
...prevState.currentWeather,
temp: fahrenheitTemp,
}
}));
}
//otherwise, celsius is checked
else {
const celsiusTemp = convertToCelsius(this.state.currentWeather.temp);
this.setState(prevState => ({
unit: '°C',
currentWeather: {
...prevState.currentWeather,
temp: celsiusTemp,
}
}));
}
}

render() {
return (
<div className='weather-app'>
<LocationInput getWeather={this.getWeather} unitHandler={this.unitHandler}/>
<CurrentWeather weatherStats={this.state.currentWeather} unit={this.state.unit} />
</div>
)
}
}

// Component where you enter your City and State
function LocationInput(props) {
return (
<div className='location-container'>
<form className='location-form' onSubmit={props.getWeather}>
<input type='text' name='city' placeholder='City'/>
<input type='text' name='country' placeholder='Country'/>
<button>Search</button>
<UnitConverter unitHandler={props.unitHandler} />
</form>
</div>
)
}

// Component to convert all units (fahrenheit <---> Celsius)
function UnitConverter(props) {
return (
<div className='unit-converter' onChange={props.unitHandler}>
<label for='fahrenheit'>
<input type='radio' name='unit' value='fahrenheit' defaultChecked/>
Fahrenheit
</label>
<label for='celsius'>
<input type='radio' name='unit' value='celsius'/>
Celsius
</label>
</div>
)
}

// Base weather component (intention of making specialized components for weekly forecast)
function Weather (props) {
const icons = {
thunderstorm: <i class="fas fa-bolt"></i>,
drizzle: <i class="fas fa-cloud-rain"></i>,
rain: <i class="fas fa-cloud-showers-heavy"></i>,
snow: <i class="far fa-snowflake"></i>,
clear: <i class="fas fa-sun"></i>,
atmosphere: 'No Icon Available',
clouds: <i class="fas fa-cloud"></i>,
};

let currentIcon = icons[props.weatherStats.main.toLowerCase()];
console.log(currentIcon);

return (
<div className={'weather-' + props.type}>
<h1>{props.location}</h1>
<h2>{props.day}</h2>
<figure className='weather-icon'>
<div className='weather-icon'>
{currentIcon}
</div>
<figcaption>
<h3 className='weather-main'>{props.weatherStats.main}</h3>
<div className='weather-desc'>{props.weatherStats.desc}</div>
{props.weatherStats.temp && <div className='weather-temp'>{Math.round(props.weatherStats.temp)}{props.unit}</div>}
</figcaption>
</figure>
</div>
)
}

// Using the specialization concept of React to create a more specific Weather component from base
function CurrentWeather(props) {
const dateObj = new Date();
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'];
const currentDay = days[dateObj.getDay()];

return (
<Weather
type={'current'}
weatherStats={props.weatherStats}
day={currentDay}
unit={props.unit}
/>
)
}

ReactDOM.render(<App />, root);
.weather-app {
text-align: center;
}

.weather-current {
display: inline-block;
}

.wf-container {
display: flex;
justify-content: center;
align-items: center;
}
<script src="https://use.fontawesome.com/releases/v5.5.0/js/all.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div class="root"></div>

最佳答案

类组件中的 return() 和函数组件中的区别,render() 在返回 dom 之前总是会重新计算其中的值,从而改变您在功能组件中的 props 可能不会返回所需的值。

你可能想尝试这个:

  let currentIcon = () => icons[props.weatherStats.main.toLowerCase()]

在您的返回中,将 {currentIcon} 更改为 {currentIcon()}

您可能需要考虑重新命名变量,例如 let getWeatherIcon

关于javascript - 重新渲染组件不会更新功能组件内的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53626974/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com