2017-05-12 96 views
0

我堅持使用條件內容呈現,具體取決於值的存在。在組件中,如果沒有給出API密鑰,我想用一個按鈕顯示一個輸入。當API密鑰使用electron-json-storage存儲並且作爲狀態時,該組件呈現另一個html。setState從一個回調內部呈現React組件中的相關內容

我的問題是我不能在組件的構建過程中分配狀態。

// @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> 
    ); 
    } 
} 

這是怎麼做到的?

回答

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> 
    ); 
} 
+2

對我來說很有意義在這種情況下 – Jon

+0

@喬恩想着現在同樣的移動storage.get和回調componentDidMount(),謝謝你的分享! –

+0

@Originato感謝您的回覆! –