在没有Redux的情况下使用React切换语言

时间:2018-09-21 10:09:26

标签: javascript reactjs weather-api

我正在尝试在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;

divclassName="desc"外,其他所有功能均可用。 desc总是落后一个阶段。我的意思是,当state.langen时,它将在hi中显示文本,反之亦然。

我刚刚开始学习React,所以代码很混乱。抱歉。

谢谢。

2 个答案:

答案 0 :(得分:1)

您有两个状态管理问题和一个执行流程问题,其中一个(或可能更多)导致您提到的行为(但无论如何都需要解决):

  1. State updates are asynchronous。这意味着this.state不会在this.setState调用后立即具有状态。

  2. 由于状态更新是异步的,因此,如果您要基于现有状态(在一些地方,包括switchLanguage)设置状态,则必须您向其传递回调的setState的版本,而不是向其传递对象的版本;在回调中,使用回调收到的最新状态对象作为参数。

  3. 执行this.setState({/*...*/desc: this.convertCode(/*...*/)})时,您要在调用convertCode之前先调用setState,然后将其返回值传递到setState作为要传递的对象的属性值。因此,即使不是上面的问题2,它也仍然存在基本的控制流问题,convertCode仍然会看到即将过期的{{1} }。

解决所有这些问题的最佳方法可能是更新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,因此我们需要使用回调形式。取而代之的是,合并这两个调用并将lang传递给this.state.lang

convertCode

this.setState(prevState => ({ loc: city_name, temp: temp, code: weather.code, isLoading: false, desc: this.convertCode(weather.code, prevState.lang), })); 中,问题#2和#3都存在:

switchLanguage

我们可以通过使用回调形式并将使用的语言传递到// 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

答案 1 :(得分:1)

您正在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")
      }));