2017-07-03 109 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