2017-07-03 150 views
0

對於ReactJS我還是比較新的,並且通過偉大的SO社區的幫助,我一直在構建一個小練習,通過點擊在兩個組件之間來回移動項目。這些項目來自我硬編碼到文件中的json數組items=[]中的數據。我想知道如何從api獲取數據,我已經閱讀了文檔,並知道我應該通過componentDidMount方法來實現,但是我陷入了搞不清如何在方法中設置狀態的問題。代碼如下...reactjs - 從api獲取數據

class SingleItem extends React.Component { 
render() { 
    let data = this.props.data; 

    return (
     <li onClick={this.props.onClick}> 
      <div> {data.name} </div> 
     </li> 
    ); 
    } 
} 

class ItemList extends React.Component { 
    render() { 
    let itemArr = this.props.allItems; 
    let myItems = this.props.items; 
    let handleEvent = this.props.handleEvent; 

    let listItems = itemArr.map((itemObj) => { 
     if (!myItems.includes(itemObj.id)) return null; 

     return <SingleItem 
      key={itemObj.id} 
      data={itemObj} 
      onClick={() => handleEvent(itemObj.id)} 
     />; 
    }); 

    return (
     <ul> 
      {listItems} 
     </ul> 
    ); 
    } 
} 

class App extends React.Component { 
    constructor(props) { 
    super(props); 

    this.state = { 
     data: [], 
     boxOne: props.items.map(item => item.id), // init the boxes with 
itemIds 
     boxTwo: [] 
    }; 

    this.handleEvent = this.handleEvent.bind(this); 
} 

handleEvent(itemId) { 
    const isInBoxOne = this.state.boxOne.includes(itemId); 

    // Heres the magic, if the item is in the first Box, filter it out, 
    // and put into the second, otherwise the other way around.. 
    this.setState({ 
     boxOne: isInBoxOne 
      ? this.state.boxOne.filter(i => i !== itemId) 
      : [ ...this.state.boxOne, itemId ], 
     boxTwo: isInBoxOne 
      ? [ ...this.state.boxTwo, itemId ] 
      : this.state.boxTwo.filter(i => i !== itemId) 
    }); 
} 
render() { 
    return (
     <div className="wrapper"> 
      <div className="box"> 
       <ItemList handleEvent={this.handleEvent} items={this.state.boxOne} allItems={this.props.items} /> 
      </div> 
      <div className="box"> 
       <ItemList handleEvent={this.handleEvent} items={this.state.boxTwo} allItems={this.props.items} /> 
      </div> 
     </div> 
    ); 
    } 
}; 

var items = [ 
    {name: "Item 1", id: 1}, 
    {name: "Item 2", id: 2}, 
    {name: "Item 3", id: 3}, 
    {name: "Item 4", id: 4}, 
    {name: "Item 5", id: 5}, 
    {name: "Item 6", id: 6} 
] 

ReactDOM.render(
    <App items={items} />, 
    document.getElementById('root') 
); 

回答

0

你可以做到這一點很容易與axios

componentDidMount() { 
    axios.get('http://myapi.com/myrequest') 
    .then((res) => {  
     this.setState({ data:res.myvalue }); // change state 
    }) 
} 

然而,做組件,專用API等之間的「全局狀態」更復雜的應用程序..你應該使用ReduxMeteor

+0

謝謝!因此,這意味着我應該將'BoxOne:'的'this.state:'更改爲一個空數組,因爲我將在''props.items.map(item => item.id)'' componentDidMount()'方法現在嗎? –

+0

我認爲你不應該直接在構造函數中獲取boxOne(和Two),而是使用'componentWillMount()'而不是像getBox(num){/ *返回數字框* /}那樣的函數' – pirs

0

嗨,你可以使用fetch api從java腳本調用api,也可以使用promise來處理結果。

0

你可以直接撥打你的HTTP componentDidMount是的。但隨着您的應用程序的增長,您將需要從組件中分離出這個邏輯。因此,你的組件將更加可重用,更易於維護。只需等待承諾完成之後再設置結果即可。

axios.get('/api/url') 
    .then(function (response) { 
    this.setState({data: response.data}) 
    }) 
    .catch(function (error) { 
    this.setState({data: [], error: true}) 
    }) 

關於庫使HTTP請求,您可以使用axios,或者superagent。無論如何,我建議你使用一個在服務器和客戶端都可以運行的庫。所以,如果你希望你的應用是同構的/通用的(由nodeJS服務器渲染),你不會遇到麻煩。

+0

然後我打電話給我的''父組件訪問API中的數據?例如,在我的渲染方法中,我有'應用程序項目= {項目}',那麼我現在會放在那裏? –

+0

我注意到你的意思,但是如果你需要上面的層次結構中的數據,你應該調用這個API並且在App父類中給出結果的狀態。然後你將數據傳遞給有道具的孩子。 – flocks