2015-02-18 24 views
10

Tôi đang cố tạo blog trong React. Trong thành phần ReactBlog chính của tôi, tôi đang thực hiện một cuộc gọi AJAX đến một máy chủ nút để trả về một mảng các bài đăng. Tôi muốn chuyển dữ liệu bài đăng này đến các thành phần khác nhau làm đạo cụ.Chuyển kết quả AJAX dưới dạng Đạo cụ cho thành phần con

Cụ thể, tôi có một thành phần được gọi là PostViewer sẽ hiển thị thông tin bài đăng. Theo mặc định, tôi muốn nó hiển thị bài đăng được gửi từ cha mẹ của nó thông qua đạo cụ và nếu không hiển thị dữ liệu được đặt qua cuộc gọi của tiểu bang.

Hiện tại, các phần có liên quan của mã của tôi trông giống như thế này.

var ReactBlog = React.createClass({ 
    getInitialState: function() { 
    return { 
     posts: [] 
    }; 
    }, 
    componentDidMount: function() { 
    $.get(this.props.url, function(data) { 
     if (this.isMounted()) { 
     this.setState({ 
      posts: data 
     }); 
     } 
    }.bind(this)); 
    }, 
    render: function() { 
    var latestPost = this.state.posts[0]; 
    return (
     <div className="layout"> 
     <div className="layout layout-sidebar"> 
      <PostList posts={this.state.posts}/> 
     </div> 
     <div className="layout layout-content"> 
      <PostViewer post={latestPost}/> 
     </div> 
     </div> 
    ) 
    } 
}); 

và thành phần con:

var PostViewer = React.createClass({ 
    getInitialState: function() { 
    return { 
     post: this.props.post 
    } 
    }, 
    render: function() { 
    /* handle check for initial load which doesn't include prop data yet */ 
    if (this.state.post) { 
     return (
     <div> 
      {this.state.post.title} 
     </div> 
    ) 
    } 
    return (
     <div/> 
    ) 
    } 
}); 

Các công trình trên nếu tôi trao đổi trên các câu lệnh if và nội dung trong con của tôi trả cho this.props * Tuy nhiên, điều này sẽ có nghĩa là tôi couldn'. t thay đổi nội dung sau này qua tiểu bang, đúng không?

TLDR: Tôi muốn đặt bài đăng mặc định được xem qua đạo cụ trong thành phần con (kết quả của cuộc gọi AJAX) và tôi muốn có thể thay đổi bài đăng đang được xem bằng cách thêm các sự kiện Click (của một sự kiện khác thành phần) sẽ cập nhật trạng thái.

Đây có phải là cách chính xác để thực hiện không?

hệ thống cấp bậc hiện tại của các thành phần ứng dụng của tôi là:

React Blog 
- Post List 
    - Post Snippet (click will callback on React Blog and update Post Viewer) 
- Post Viewer (default post passed in via props) 

Cảm ơn!

EDIT:

Vì vậy, những gì tôi đã kết thúc làm được gắn các đạo cụ trong ReactBlog sử dụng một giá trị dựa trên this.state. Điều này đảm bảo rằng nó cập nhật khi tôi thay đổi trạng thái và hiển thị chính xác trong các thành phần con. Tuy nhiên, để làm điều này tôi đã phải chuỗi onClick callbacks lên thông qua tất cả các thành phần con khác nhau. Điều này có đúng không? Nó có vẻ như nó có thể nhận được VERY lộn xộn. Đây là mã ví dụ đầy đủ của tôi:

var ReactBlog = React.createClass({ 
    getInitialState: function() { 
    return { 
     posts: [], 
    }; 
    }, 
    componentDidMount: function() { 
    $.get(this.props.url, function(data) { 
     if (this.isMounted()) { 
     this.setState({ 
      posts: data, 
      post: data[0] 
     }); 
     } 
    }.bind(this)); 
    }, 
    focusPost: function(slug) { 
    $.get('/api/posts/' + slug, function(data) { 
     this.setState({ 
     post: data 
     }) 
    }.bind(this)); 
    }, 
    render: function() { 
    return (
     <div className="layout"> 
     <div className="layout layout-sidebar"> 
      <PostList handleTitleClick={this.focusPost} posts={this.state.posts}/> 
     </div> 
     <div className="layout layout-content"> 
      <PostViewer post={this.state.post}/> 
     </div> 
     </div> 
    ) 
    } 
}); 

var PostList = React.createClass({ 
    handleTitleClick: function(slug) { 
    this.props.handleTitleClick(slug); 
    }, 
    render: function() { 
    var posts = this.props.posts; 

    var postSnippets = posts.map(function(post, i) { 
     return <PostSnippet data={post} key={i} handleTitleClick={this.handleTitleClick}/>; 
    }, this); 

    return (
     <div className="posts-list"> 
     <ul> 
      {postSnippets} 
     </ul> 
     </div> 
    ) 
    } 
}); 

var PostSnippet = React.createClass({ 
    handleTitleClick: function(slug) { 
    this.props.handleTitleClick(slug); 
    }, 
    render: function() { 
    var post = this.props.data; 
    return (
     <li> 
     <h1 onClick={this.handleTitleClick.bind(this, post.slug)}>{post.title}</h1> 
     </li> 
    ) 
    } 
}); 

var PostViewer = React.createClass({ 
    getInitialState: function() { 
    return { 
     post: this.props.post 
    } 
    }, 
    render: function() { 
    /* handle check for initial load which doesn't include prop data yet */ 
    if (this.props.post) { 
     return (
     <div> 
      {this.props.post.title} 
     </div> 
    ) 
    } 
    return (
     <div/> 
    ) 
    } 
}); 

Vẫn hy vọng nhận được một số phản hồi/hy vọng điều này sẽ hữu ích!

+0

Bạn đang làm tất cả ngay sau phiên bản. Sử dụng một tiểu bang trong một thành phần phụ huynh để cung cấp với đạo cụ cho trẻ em là con đường để đi. Vấn đề của bạn là "getInitialState" chỉ thực hiện một lần cho mỗi thành phần (trừ khi nó chưa được gắn kết) vì vậy khi bạn thay đổi trạng thái gốc, ngay cả khi đạo cụ con cũng thay đổi, trạng thái của nó sẽ không. – GonArrivi

Trả lời

0

Blog là tĩnh cho hầu hết các phần, vì vậy bạn có thể khai thác các cấu trúc không thay đổi React để "hiển thị mọi thứ" mọi lúc thay vì sử dụng trạng thái.

Một tùy chọn cho việc này là sử dụng bộ định tuyến (như page.js) để tìm nạp dữ liệu.

Dưới đây là một số mã http://jsbin.com/qesimopugo/1/edit?html,js,output

Nếu bạn không hiểu điều gì đó chỉ cho tôi biết;)

0

Nhà nước nên có chính phản ứng xem tập tin, không cho các thành phần tái sử dụng, như ở đây PostViewer, nó sẽ chỉ hiển thị tiêu đề bài đăng nếu nó có tiêu đề làm đạo cụ, nếu không nó sẽ hiển thị trống.

var PostViewer = React.createClass({ 

    render: function() { 

    if (this.props.hasOwnProperty('title')) { 
     return (
     <div> 
      {this.props.title} 
     </div> 
    ) 
    } 
    return (
     <div/> 
    ) 
    } 
}); 
2

Đây là một câu hỏi cũ, nhưng tôi tin rằng vẫn còn phù hợp, vì vậy tôi sẽ ném vào tôi 2 xu.

Lý tưởng nhất là bạn muốn tách riêng mọi cuộc gọi ajax thành tệp tác vụ thay vì thực hiện ngay bên trong thành phần. Không cần sử dụng thứ gì đó như Redux để giúp bạn quản lý trạng thái của bạn (vào thời điểm này, tôi khuyên bạn nên sử dụng redux + react-redux), bạn có thể sử dụng thứ gọi là "thành phần container" bạn và sau đó sử dụng đạo cụ trong thành phần đang thực hiện bố cục chính. Dưới đây là ví dụ:

// childComponent.js 
import React from 'react'; 
import axios from 'axios'; // ajax stuff similar to jquery but with promises 

const ChildComponent = React.createClass({ 
    render: function() { 
    <ul className="posts"> 
     {this.props.posts.map(function(post){ 
     return (
      <li> 
      <h3>{post.title}</h3> 
      <p>{post.content}</p> 
      </li> 
     ) 
     })} 
    </ul> 
    } 
}) 

const ChildComponentContainer = React.createClass({ 
    getInitialState: function() { 
    return { 
     posts: [] 
    } 
    }, 
    componentWillMount: function() { 
    axios.get(this.props.url, function(resp) { 
     this.setState({ 
     posts: resp.data 
     }); 
    }.bind(this)); 
    }, 
    render: function() { 
    return (
     <ChildComponent posts={this.state.posts} /> 
    ) 
    } 
}) 

export default ChildComponentContainer; 
+0

điều này chắc chắn là một cách tuyệt vời để làm điều đó :) – Jon

Các vấn đề liên quan