【问题标题】:setState won't update React clocksetState 不会更新 React 时钟
【发布时间】:2023-04-09 01:11:01
【问题描述】:

我目前正在使用 React 构建一个简单的应用程序,而且我对它还比较陌生,所以我觉得我的解决方案是一个简单的解决方案,只是我还没有经验。

基本上,该应用程序允许用户输入世界上任何城市的名称,并且输出会更新输入下方的 React 实时时钟组件。为此,我使用城市时区库来获取用户所需城市的数据,moment.js 将城市时间解析为所需时区,当然还有 React 实时时钟来向用户显示实际时间。

在我的 loadTime 函数中,我检索了 timezone 属性并将其传递给我的 moment().tz() 方法进行解析。在我将state 传递到我的setState() 并将更新的状态打印到控制台之后,它确实显示了正确的状态。例如,用户键入 Tokyo 并返回键/值 timezone: "Asia/Tokyo"

我的问题是,在将 this.state.timezone 传递到我的 React 实时时钟组件 timezone 属性并单击“获取时间”按钮后,我的时钟实际上并没有更新状态,而是保持用户浏览器的当前时间.

我已经确定我的loadTime() 函数可以正常工作,所以我相信我的时钟组件没有正确连接以读取更新的timezone 状态。正如我的问题所述,另一种可能性是我错误地使用了setState()

这里有什么我忽略的地方,还是我在滥用setState() 时走在正确的轨道上?


import Moment from 'moment-timezone';
import cityTimezones from 'city-timezones';
import Clock from 'react-live-clock';
let moment = require('moment-timezone');

export default class Search extends Component {

  state = {
    userLocation: "",
    localTime: "",
    rows: [],

  };

  //Methods
  loadTime = (searchTerm) => {
    const city = cityTimezones.lookupViaCity(searchTerm);
    let state = this.state; 
    if (city.length > 0) { 
      const timezone = city[0].timezone;    
      let now = moment().tz(timezone).format('h:mm:ss a');           
      state.localTime = now;         
      state.timezone = timezone;   
    } else {
      state.userLocation = "";
      state.localTime = "";
    };
    this.setState(state);  
    console.log(state);      
  };

    handleChange = (e) => {
      let state = this.state;
      state[e.target.name] = e.target.value;
      this.setState(state);   
    }

    //Create
    handleClick = (e) => {
      e.preventDefault();
      this.loadTime(this.state.userLocation);
    };

    render () {
      let alert = (!this.state.localTime) ? "Please enter location": "";

      return (
        <div className="search-container-fluid gradient p-3">
          <div className="row">
            <div className="search-container">
                <input onChange={this.handleChange} name="userLocation" type="text" 
                 className="form-control" placeholder="Enter a location" />
                <button onClick={this.handleClick} name="search-btn" className="btn btn-search" 
                 type="button" >Get time.</button>
              <div className="output-container mt-5">
                <Clock ticking={true} format={'hh:mm:ss a'} timezone={this.state.timezone} />                             
                {/* {alert} */}
              </div>
            </div>
          </div>
        </div>
      )
    }
  };``` 

【问题讨论】:

  • 你直接在各处改变状态。永远不要在 React 中这样做,它会导致问题。仅通过 this.setState 更新状态(或在功能组件中,仅使用关联的钩子函数)。如果您需要更新深度嵌套的值,请先对状态进行深度克隆,改变那个,然后将状态设置为该克隆对象
  • 如果你想更新状态 - this.setState( {'statename',value}).. 在你的情况下 this.setState({userLocation:'xyz'})
  • 我重构了我的代码,以便对我的状态所做的更改在setState() 内部完成,如下所示:loadTime = (searchTerm) =&gt; { const city = cityTimezones.lookupViaCity(searchTerm); let state = this.state; //Get access to local state const timezone = city[0].timezone; let now = moment().tz(timezone).format('h:mm:ss a'); this.setState({ userLocation: state.userLocation, localTime: now, timezone: timezone, }); console.log(state); } 但是这并没有解决我的 React 没有更新 UI 的问题.
  • 您正在两次抓取时刻时区。 Jayce444 也是正确的,因为你直接改变了状态。您的句柄更改可能类似于 handleChange = (e) =&gt; { this.setState(prevState =&gt; ({ ...prevState, [e.target.name] = e.target.value, }) }
  • 感谢大家的帮助。我已更改代码以反映setState() 中的更新状态,但是状态更改根本不会显示在 UI 中。我的猜测是,要么我在我的 Clock 组件中使用了不正确的属性,要么我需要在我的默认状态对象中初始化一个时区变量,而不是在我的 loadTime() 函数中。

标签: javascript reactjs timezone momentjs setstate


【解决方案1】:

由于 react 无法识别更改,因此您在此处直接操作状态,请尝试以下代码

 //Methods


loadTime = (searchTerm) => {
    const city = cityTimezones.lookupViaCity(searchTerm);
    let state = {...this.state}; 
    if (city.length > 0) { 
      const timezone = city[0].timezone;    
      let now = moment().tz(timezone).format('h:mm:ss a');           
      state.localTime = now;         
      state.timezone = timezone;   
    } else {
      state.userLocation = "";
      state.localTime = "";
    };
    this.setState(state);  
    console.log(state);      
  };

handleChange = (e) => {
  let state = {...this.state};
  state[e.target.name] = e.target.value;
  this.setState(state);   
}

【讨论】:

    猜你喜欢
    • 2018-02-06
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多