2017-07-03 23 views
0

私はまだReactJSを新しくしていますし、すばらしいSOコミュニティの助けを借りて、クリックで2つのコンポーネント間でアイテムを前後に移動する小さなエクササイズを構築しています。これらの項目は、ファイルにハードコードされたjson配列items=[]のデータから来ています。私はどのように私は、ドキュメントを読んで、私はcomponentDidMountメソッドを介してそれを行う必要があることを知っているが、私は、メソッドの状態を設定する方法を把握しているつもりです。コードは、あなたがなどのコンポーネント、専用のAPIとの間の「グローバルな状態」で、より複雑なアプリケーションを実行するために、しかしaxiosreactjs - apiからデータを取得する

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

をそれを行うことができ...以下

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

..ですReduxまたはMeteor

+0

ありがとうございます!つまり、 'BoxOne:'の 'this.state:'を空の配列に変更しなければならないということです。 'props.items.map(item => item.id)'で状態を設定するので、 componentDidMount() 'メソッドは今ですか? –

+0

あなたはboxOne(とTwo)を直接コンストラクタで取得せず、代わりに 'getBox(num){/ * num boxを返す* /}'のような関数を使って 'componentWillMount()'を使うべきだと思います。 – pirs

0

こんにちは、api呼び出しのためのJavaスクリプトからfetch apiを使用して、結果を処理するために約束を使用することもできます。

0

componentDidMountでHTTPを直接呼び出すことができます。しかし、アプリが大きくなるにつれて、このロジックをコンポーネントから分離したいと考えています。したがって、コンポーネントは再利用可能で保守性が向上します。あなたの状態を結果で設定する前に、約束が成就するのを待ってください。 HTTPリクエストを作成するためのライブラリについて

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

、あなたはaxios、またはsuperagentを使用することができます。とにかく、サーバーとクライアントの両方のサイトで動作するライブラリを使用することをお勧めします。だからあなたのアプリが同型/汎用(nodeJSサーバによってレンダリングされる)にしたいなら、あなたは困っていることはありません。

+0

APIのデータにアクセスするには、私の ''親コンポーネントを呼びますか?たとえば、私のレンダー方法では、 'App items = {items}'を持っています。 –

+0

あなたは何を意味するのか確信していますが、上記のデータが階層内に必要な場合は、APIを呼び出して、状態をAppの親に返す必要があります。次に、小道具で子供にデータを渡します。 – flocks

関連する問題