我坚持使用条件内容呈现,具体取决于值的存在。在组件中,如果没有给出API密钥,我想用按钮显示输入。当使用electron-json-storage
存储API密钥并作为状态时,该组件将呈现另一个html。
我的问题是我无法在组件构建期间分配状态。
// @flow
import React, { Component } from 'react';
import storage from 'electron-json-storage';
import {
Button,
Popover,
PopoverInteractionKind,
Position
} from '@blueprintjs/core';
export default class UserButton extends Component {
constructor() {
super();
// -----------------------------------------------------------
// HERE - I'm trying to assign keys from storage via callback
// Unfortunately it doesn't work
// It throws Cannot read property 'is_loggedin' of null
// when renders content={loginContent[this.state.is_loggedin]}
// -----------------------------------------------------------
storage.get('auth', (error, data) => {
if (error) throw error;
this.state = {
api_key: data.user.api_key,
is_loggedin: data.user.is_loggedin
};
});
this.handleTextChange = this.handleTextChange.bind(this);
this.handleSaveClick = this.handleSaveClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
}
handleTextChange(e) {
this.setState({ api_key: e.target.value });
}
handleSaveClick() {
this.setState({ is_loggedin: 1 });
storage.set('auth', { user: this.state }, function (error) {
if (error) throw error;
});
this.forceUpdate();
}
handleLogoutClick() {
this.setState({ is_loggedin: 0 });
storage.remove('auth', function (error) {
if (error) throw error;
});
this.forceUpdate();
}
render() {
const loginContent = ([
// Not logged in
<div>
<label className="pt-label .modifier">
<input
onChange={this.handleTextChange}
autoFocus={true}
className="pt-input modifier"
type="text"
placeholder="Your API key"
/>
</label>
<Button
className="pt-intent-primary pt-fill"
onClick={this.handleSaveClick}
>
Save
</Button>
</div>,
// Logged in
<div>
<Button
className="pt-intent-primary pt-fill"
onClick={this.handleLogoutClick}
>
Change API key
</Button>
</div>
]);
return (
<Popover
content={loginContent[this.state.is_loggedin]}
interactionKind={PopoverInteractionKind.CLICK}
position={Position.BOTTOM_RIGHT}
popoverClassName="pt-popover-content-sizing"
>
<Button className="pt-button pt-minimal pt-icon-user" />
</Popover>
);
}
}
如何做到这一点?
答案 0 :(得分:2)
您可能在调用回调之前渲染组件,因此state
仍为空。你可以做的是在构造函数中添加一个临时的is_loading
状态,在页面中呈现加载消息/微调器,直到调用回调为止。
constructor() {
super();
this.state = { is_loading: true };
storage.get('auth', (error, data) => {
if (error) throw error;
this.setState({
is_loading: false,
api_key: data.user.api_key,
is_loggedin: data.user.is_loggedin
});
});
this.handleTextChange = this.handleTextChange.bind(this);
this.handleSaveClick = this.handleSaveClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
}
// ...
render() {
// ...
return (
<Popover
content={this.state.is_loading? "<div>Loading...</div>": loginContent[this.state.is_loggedin]}
interactionKind={PopoverInteractionKind.CLICK}
position={Position.BOTTOM_RIGHT}
popoverClassName="pt-popover-content-sizing"
>
<Button className="pt-button pt-minimal pt-icon-user" />
</Popover>
);
}