【发布时间】: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) => { 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) => { this.setState(prevState => ({ ...prevState, [e.target.name] = e.target.value, }) } -
感谢大家的帮助。我已更改代码以反映
setState()中的更新状态,但是状态更改根本不会显示在 UI 中。我的猜测是,要么我在我的 Clock 组件中使用了不正确的属性,要么我需要在我的默认状态对象中初始化一个时区变量,而不是在我的loadTime()函数中。
标签: javascript reactjs timezone momentjs setstate