在没有 Redux 的情况下使用 React 切换语言
Toggle language using React without Redux
我正在尝试在 React 中创建一个天气应用程序。我想使用 onClick
.
切换应用语言
到目前为止,这是我的代码。
import React, { Component } from "react";
import axios from "axios";
import "./App.css";
class App extends Component {
componentDidMount() {
this.setState({
isLoading: true
});
axios
.get("path to weather api")
.then(res => {
console.log(res.data.data[0]);
const { city_name, temp, weather } = res.data.data[0];
this.setState({
loc: city_name,
temp: temp,
code: weather.code,
isLoading: false
});
this.setState({
desc: this.convertCode(this.state.code)
});
});
}
switchLanguage = () => {
if (this.state.lang === "en") {
this.setState({
lang: "hi",
desc: this.convertCode(this.state.code)
});
} else {
this.setState({
lang: "en",
desc: this.convertCode(this.state.code)
});
}
};
convertCode = givenCode => {
if (this.state.lang === "en") {
if (
givenCode === 200 ||
givenCode === 201 ||
givenCode === 202 ||
givenCode === 230 ||
givenCode === 231 ||
givenCode === 232 ||
givenCode === 233 ||
givenCode === "200" ||
givenCode === "201" ||
givenCode === "202" ||
givenCode === "230" ||
givenCode === "231" ||
givenCode === "232" ||
givenCode === "233"
) {
return "Thunderstorms";
} else if (
givenCode === 300 ||
givenCode === 301 ||
givenCode === 302 ||
givenCode === "300" ||
givenCode === "301" ||
givenCode === "302"
) {
return "Drizzle";
}
..............
..............
IF CONDITION FOR THE OTHER LANGUAGE
};
render() {
if (!this.state.isLoading) {
return (
<div className="App">
<div className="container">
<div className="languageSwitcher">
<i className="fa fa-language" onClick={this.switchLanguage} />
</div>
<div className="location">
<i className="fa fa-location-arrow" /> {this.state.loc}
</div>
{this.state.lang === "en" && (
<div className="temperature">It's {this.state.temp} degrees.</div>
)}
{this.state.lang === "hi" && (
<div className="temperature">
तापमान {this.state.temp} डिग्री है।
</div>
)}
<div className="description">{this.state.desc}</div>
</div>
</div>
);
} else {
return <div className="loading">Fetching weather data...</div>;
}
}
}
export default App;
除了 div
和 className="desc"
之外,一切正常。 desc
总是落后一个阶段。我的意思是当 state.lang
是 en
时,它显示 hi
中的文本,反之亦然。
我刚开始学习 React,所以代码很乱。抱歉。
谢谢。
您有两个状态管理问题和一个执行流程问题,其中一个(或可能更多)导致您提到的行为(但无论如何都需要修复):
State updates are asynchronous。这意味着 this.state
不会 在 this.setState
调用后立即具有更新状态。
因为状态更新是异步的,如果你根据现有状态设置状态(你在几个地方,包括switchLanguage
),你必须 使用你向其传递回调的 setState
版本,而不是你向其传递对象的版本;在回调中,使用回调接收的最新状态对象作为参数。
当您执行 this.setState({/*...*/desc: this.convertCode(/*...*/)})
时,您在 调用 setState
之前调用 convertCode
,并传递其 return 值转换为 setState
作为您传递给它的对象上的 属性 的值。因此,即使不是上面的问题 #2,它仍然会有一个基本的控制流问题,并且 convertCode
仍然会看到即将过时的 this.state.lang
.
解决所有这些问题的最佳方法可能是更新 convertCode
以选择性地接受要使用的 lang
(默认为 this.state.lang
):
convertCode = (givenCode, lang = this.state.lang) => {
// ...use `lang`, not `this.state.lang`...
...然后解决设置状态和使用 convertCode
的各种问题。第一个在 componentDidMount
:
componentDidMount() {
this.setState({
isLoading: true
});
axios
.get("path to weather api")
.then(res => {
console.log(res.data.data[0]);
const { city_name, temp, weather } = res.data.data[0];
this.setState({
loc: city_name,
temp: temp,
code: weather.code,
isLoading: false
});
this.setState({
desc: this.convertCode(this.state.code) // <=== Error is here
});
});
}
this.state.code
还没有更新,因为状态更新是异步的。另外,我们要使用this.state.lang
,所以需要使用回调形式。相反,合并这两个调用并将 lang 传递给 convertCode
:
this.setState(prevState => ({
loc: city_name,
temp: temp,
code: weather.code,
isLoading: false,
desc: this.convertCode(weather.code, prevState.lang),
}));
在switchLanguage
中,问题#2 和#3 都存在:
// INCORRECT:
// A) Sets state based on state without callback
// B) Calls `convertCode` before `setState`
switchLanguage = () => {
if (this.state.lang === "en") {
this.setState({
lang: "hi",
desc: this.convertCode(this.state.code)
});
} else {
this.setState({
lang: "en",
desc: this.convertCode(this.state.code)
});
}
};
我们可以通过使用回调形式并将要使用的语言传递给 convertCode
:
来解决这两个问题
// Uses callback when setting state based on state
switchLanguage = () => {
this.setState(prevState => {
const lang = prevState.lang === "en" ? "hi": "en";
return {lang, desc: this.convertCode(prevState.code, lang)};
});
};
注意 prevState
的使用既用于 lang
检查,也用于将 code
传递给 this.convertCode
。
您在 convertCode
方法中使用以前的语言状态,您可以将新的语言传递给它:
convertCode = (givenCode, lang) => {
if (lang === "en") {
...
然后在您的 switchLanguage
方法中:
this.setState({
lang: "hi",
desc: this.convertCode(this.state.code, "hi")
});
编辑:更喜欢setState的功能版本以避免在this.state.code
更新的情况下出现不一致:
this.setState(prevState => ({
lang: "hi",
desc: this.convertCode(prevState.code, "hi")
}));
我正在尝试在 React 中创建一个天气应用程序。我想使用 onClick
.
到目前为止,这是我的代码。
import React, { Component } from "react";
import axios from "axios";
import "./App.css";
class App extends Component {
componentDidMount() {
this.setState({
isLoading: true
});
axios
.get("path to weather api")
.then(res => {
console.log(res.data.data[0]);
const { city_name, temp, weather } = res.data.data[0];
this.setState({
loc: city_name,
temp: temp,
code: weather.code,
isLoading: false
});
this.setState({
desc: this.convertCode(this.state.code)
});
});
}
switchLanguage = () => {
if (this.state.lang === "en") {
this.setState({
lang: "hi",
desc: this.convertCode(this.state.code)
});
} else {
this.setState({
lang: "en",
desc: this.convertCode(this.state.code)
});
}
};
convertCode = givenCode => {
if (this.state.lang === "en") {
if (
givenCode === 200 ||
givenCode === 201 ||
givenCode === 202 ||
givenCode === 230 ||
givenCode === 231 ||
givenCode === 232 ||
givenCode === 233 ||
givenCode === "200" ||
givenCode === "201" ||
givenCode === "202" ||
givenCode === "230" ||
givenCode === "231" ||
givenCode === "232" ||
givenCode === "233"
) {
return "Thunderstorms";
} else if (
givenCode === 300 ||
givenCode === 301 ||
givenCode === 302 ||
givenCode === "300" ||
givenCode === "301" ||
givenCode === "302"
) {
return "Drizzle";
}
..............
..............
IF CONDITION FOR THE OTHER LANGUAGE
};
render() {
if (!this.state.isLoading) {
return (
<div className="App">
<div className="container">
<div className="languageSwitcher">
<i className="fa fa-language" onClick={this.switchLanguage} />
</div>
<div className="location">
<i className="fa fa-location-arrow" /> {this.state.loc}
</div>
{this.state.lang === "en" && (
<div className="temperature">It's {this.state.temp} degrees.</div>
)}
{this.state.lang === "hi" && (
<div className="temperature">
तापमान {this.state.temp} डिग्री है।
</div>
)}
<div className="description">{this.state.desc}</div>
</div>
</div>
);
} else {
return <div className="loading">Fetching weather data...</div>;
}
}
}
export default App;
除了 div
和 className="desc"
之外,一切正常。 desc
总是落后一个阶段。我的意思是当 state.lang
是 en
时,它显示 hi
中的文本,反之亦然。
我刚开始学习 React,所以代码很乱。抱歉。
谢谢。
您有两个状态管理问题和一个执行流程问题,其中一个(或可能更多)导致您提到的行为(但无论如何都需要修复):
State updates are asynchronous。这意味着
this.state
不会 在this.setState
调用后立即具有更新状态。因为状态更新是异步的,如果你根据现有状态设置状态(你在几个地方,包括
switchLanguage
),你必须 使用你向其传递回调的setState
版本,而不是你向其传递对象的版本;在回调中,使用回调接收的最新状态对象作为参数。当您执行
this.setState({/*...*/desc: this.convertCode(/*...*/)})
时,您在 调用setState
之前调用convertCode
,并传递其 return 值转换为setState
作为您传递给它的对象上的 属性 的值。因此,即使不是上面的问题 #2,它仍然会有一个基本的控制流问题,并且convertCode
仍然会看到即将过时的this.state.lang
.
解决所有这些问题的最佳方法可能是更新 convertCode
以选择性地接受要使用的 lang
(默认为 this.state.lang
):
convertCode = (givenCode, lang = this.state.lang) => {
// ...use `lang`, not `this.state.lang`...
...然后解决设置状态和使用 convertCode
的各种问题。第一个在 componentDidMount
:
componentDidMount() {
this.setState({
isLoading: true
});
axios
.get("path to weather api")
.then(res => {
console.log(res.data.data[0]);
const { city_name, temp, weather } = res.data.data[0];
this.setState({
loc: city_name,
temp: temp,
code: weather.code,
isLoading: false
});
this.setState({
desc: this.convertCode(this.state.code) // <=== Error is here
});
});
}
this.state.code
还没有更新,因为状态更新是异步的。另外,我们要使用this.state.lang
,所以需要使用回调形式。相反,合并这两个调用并将 lang 传递给 convertCode
:
this.setState(prevState => ({
loc: city_name,
temp: temp,
code: weather.code,
isLoading: false,
desc: this.convertCode(weather.code, prevState.lang),
}));
在switchLanguage
中,问题#2 和#3 都存在:
// INCORRECT:
// A) Sets state based on state without callback
// B) Calls `convertCode` before `setState`
switchLanguage = () => {
if (this.state.lang === "en") {
this.setState({
lang: "hi",
desc: this.convertCode(this.state.code)
});
} else {
this.setState({
lang: "en",
desc: this.convertCode(this.state.code)
});
}
};
我们可以通过使用回调形式并将要使用的语言传递给 convertCode
:
// Uses callback when setting state based on state
switchLanguage = () => {
this.setState(prevState => {
const lang = prevState.lang === "en" ? "hi": "en";
return {lang, desc: this.convertCode(prevState.code, lang)};
});
};
注意 prevState
的使用既用于 lang
检查,也用于将 code
传递给 this.convertCode
。
您在 convertCode
方法中使用以前的语言状态,您可以将新的语言传递给它:
convertCode = (givenCode, lang) => {
if (lang === "en") {
...
然后在您的 switchLanguage
方法中:
this.setState({
lang: "hi",
desc: this.convertCode(this.state.code, "hi")
});
编辑:更喜欢setState的功能版本以避免在this.state.code
更新的情况下出现不一致:
this.setState(prevState => ({
lang: "hi",
desc: this.convertCode(prevState.code, "hi")
}));