代码之家  ›  专栏  ›  技术社区  ›  sequel

使用React without Redux切换语言

  •  1
  • sequel  · 技术社区  · 6 年前

    我正在尝试在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 反之亦然。

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

    2 回复  |  直到 6 年前
        1
  •  1
  •   T.J. Crowder    6 年前

    您有两个状态管理问题和一个执行流问题,其中一个(或可能多个)导致您提到的行为(但在任何情况下都需要修复):

    1. State updates are asynchronous . 这意味着 this.state 在事件发生后立即更新状态 this.setState 打电话。

    2. 因为状态更新是异步的,如果您是基于现有状态设置状态(您在一些地方,包括 switchLanguage ),你 必须 setState

    3. 当你这么做的时候 this.setState({/*...*/desc: this.convertCode(/*...*/)}) ,你在打电话吗 convertCode 之前 打电话 ,并将其返回值传递到 设置状态 作为对象上属性的值传递。因此,即使不是针对上面的问题2,它仍然有一个基本的控制流和问题 转换码 仍然会看到这本书即将过时 this.state.lang .

    转换码 有选择地接受 lang 使用(默认为 ):

    convertCode = (givenCode, lang = this.state.lang) => {
        // ...use `lang`, not `this.state.lang`...
    

    . 第一个是 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传递给 :

            this.setState(prevState => ({
              loc: city_name,
              temp: temp,
              code: weather.code,
              isLoading: false,
              desc: this.convertCode(weather.code, prevState.lang),
            }));
    

    ,问题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)
          });
        }
      };
    

    我们可以通过使用回调表单并将要使用的语言传递到 转换码 :

    // 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 都是为了 检查并通过 code this.convertCode .

        2
  •  1
  •   Dyo    6 年前

    convertCode 方法,则可以将新的lang传递给它:

    convertCode = (givenCode, lang) => {
        if (lang === "en") {
            ...
    

    switchLanguage 方法:

    this.setState({
            lang: "hi",
            desc: this.convertCode(this.state.code, "hi")
          });
    

    编辑 this.state.code 更新:

    this.setState(prevState => ({
            lang: "hi",
            desc: this.convertCode(prevState.code, "hi")
          }));