2017-10-02 9 views
0

状態の変更が可能なときに状態コンポーネントを使用するReactJSのベストプラクティスに従うようにしていますが、コンポーネントが状態を保持していないときに役立ちますが、両方の型を可能にするために私のコンポーネントを構造化します。現在、私はJSONファイルを取得して、個々のオブジェクトを状態コンポーネント内に設定しています。そして、それぞれの情報について個々のプロップコンポーネントを使用してその情報の設計とレイアウトを構造化したいと考えています。 propコンポーネントは、私が渡しているプロパティーがundefinedというレンダリングエラーです。これは親子コンポーネントの問題ですか?ここでReactJS - 状態からプロップへの戻りオブジェクト

は(レンダリングされているトップレベル、)私の見解フィードは次のとおりです。

export default class CommentFeed extends React.Component { 

    render() { 
     return (
      <div className="comment-feed"> 
       <Comments /> 
      </div> 
     ); 
    } 
} 

は、次にフェッチと状態コンポーネントとして設定マイ:

//Comments List 
class Comments extends React.Component{ 

    constructor(props, context) { 
     super(props, context); 
     this.state = this.context.data || window.__INITIAL_STATE__ || {users: []}; 
    } 

    fetchList() { 
     fetch('http://localhost:3000/api/test') 
      .then(res => { 
       return res.json(); 
      }) 
      .then(data => { 
       console.log(data); 
       let users = data.map((user, index) => { 
        return(
         <div key={index}> 
         <UserTitle title={user.title} /> 
         <li>{user.discovery}</li> 
         <ul> 
         { 
          user.user_comments.map((comment, i) => { 
           console.log("this is the comment " + JSON.stringify(comment)); 
           console.log("this is the i " + i); 
           return (
             <div key={comment.userCommentId}> 
             <h4>{comment.app_user.fullNameSlug}</h4> 
             <li>{comment.comment}</li> 
             </div> 
           ) 
          }) 
         } 
         </ul> 
         </div> 
        ) 
       }) 
       this.setState({ users: users }); 
      }) 
      .catch(err => { 
       console.log(err); 
      }); 
    } 

    componentDidMount() { 
     this.fetchList(); 
    } 

    render() { 
     return (
      <div> 
      <h2>Comments List</h2> 
      <ul> 
      {this.state.users} 
      </ul> 
      </div> 
     ) 
    } 
}; 

そして、ここれます<UserTitle />プロップコンポーネント:

class UserTitle extends React.Component{ 
    render(props){ 
     return (
      <div className="test"> 
       <h1>{props.title}</h1> 
      </div> 
     ) 
    } 
} 
+0

レンダリングされたものを状態に格納しないでしょうか?それはあなたにかなり肥大した状態を与えます。状態を非同期の結果として設定し、レンダリングの内容をレンダリングします。 this.state.usersの.mapを直接レンダリング関数または一部のサブレンダリングメソッドに置くことができます。 コンポーネントの場合、常にnullを返すことができます。したがって、プロップが指定されていない場合は、レンダリング関数でnullを返すだけですか? – thsorens

+0

それは{this.props.title}ではない{props.title}も私はレンダリングにはパラメータがないと思う – Mahmoud

+0

私は同じことを言い表せなかった。レンダーには何のパラメータもありません。これを参照する必要があります。 – thsorens

答えて

3

あなたは状態のユーザーの配列を保存することができますfetchList

const UserComments = ({ comments }) => 
    <ul> 
    {comments.map(comment => 
     <li key={comment.userCommentId}> 
     <h4>{comment.app_user.fullNameSlug}</h4> 
     <span>{comment.comment}</span> 
     </li> 
    )} 
    </ul> 

const User = ({ user }) => 
    <div> 
    <UserTitle={user.title} /> 
    <span>{user.discovery}</span> 
    <UserComments comments={user.user_comments} /> 
    </div> 

。 「コミュニティ」で一般に

我々はコンポーネントの通常2種類があります。

  • コンテナコンポーネントを
  • ビューコンポーネント(ダムのコンポーネント)は、ビジネスロジックを処理する必要があります

コンテナコンポーネント、データ、アクションなどを取得し、必要なデータをビューコンポーネントに渡します。

ビューコンポーネントは、ビューを表示するだけで、データを取得せず、取得しません。主に、彼らはので、ここであなたが持っているために必要なものを簡単に図である

(常にではない)であっても、自分の状態を持っていけない: は - CommentsContainer - CommentsFeedView - それはコード内で基本的にどのように見えるべきかCommentView

class CommentsContainer extends Component { 
    constructor(props) { 
     super(props) 
     this.state = { 
      comments = [], 
      loading: false 
     } 
    } 


    componentDidMount() { 
     someAjaxCall('get', '/comments') 
      .then(data => { 
        this.setState({comments: data, loading: false}) 
       }).bind(this) 
    } 

    render() { 
     return <CommentsFeedView {...this.state} /> 
    } 
} 


const CommentsFeedView = props => { 
    return (
     <div> 
      {props.comments.map(comment => <CommentView {...comment} />} 
     </div> 
    ) 
} 

const CommentView = props => { 
    return (
     <div> 
      <h4>{props.title}</h4> 
      <p>{props.content}</p> 
     </div> 
    ) 
} 

ネストマップを作成する場合は、考え方を変更する必要があります。 コンポーネントをコンテンツをレンダリングするブラックボックスと考えてください。 より複雑なコンポーネントがあるかもしれません。他のコンポーネントと1つのライナーをレンダリングするコンポーネント。

だから、これはちょうどあなたが持っている質問のコードのような例です。

class UsersCommentsFeed { 
    render() { 
     return (
      {this.props.users.map(user => <SingleUserComments {...user} />)} 
     ) 
    } 
} 

class SingleUserComments { 
    render() { 
     return (
      {this.props.comments.map(comment => <Comment {...comment} />)} 
     ) 
    } 
} 

class Comment { 
    render() { 
     return (
      <div> 
       <h2>{this.props.title}</h2> 
       <p>{this.props.content}</p> 
      </div> 
     ) 
    } 
} 

あなたがここに見ることができるよう、私たちは本当にマップ、またはネストされたマップを気にしないでください。各コンポーネントはそれ自身をレンダリングし、「外側」を気にしません

+0

これは素晴らしい説明です。手伝ってくれてどうもありがとう! – cphill

+0

'CommentsFeedView'コンポーネントでネストされたマップがどのように見えるかの簡単な例を提供できますか?あなたが私の質問に気づくかもしれませんが、コメントセクションはユーザーマップ – cphill

+0

内のマップです。確かに、コメントのリストだけで、そのコメントのコメントのリスト。後で更新されます –

0

および<ul>{user.user_comments.map(...)}</ul>は、同じUserコンポーネント(名前は任意です)の一部であるようです。

コンポーネントをコールバック内にレンダリングする代わりに(コンポーネントを状態に保存するためにはお勧めできません)、私の提案は、すべてのユーザーの詳細を処理する単一のコンポーネントを作成することです。

コードやコンポーネントを再利用可能(例:UserTitle)にしてテスト可能です。ユーザーが何らかの方法で変更するたびに大きなビジネスロジックを更新する必要はありません。

fetchList() { 
    fetch('http://localhost:3000/api/test') 
    .then(res => res.json()) 
    .then(data => this.setState({ users: data })) 
} 

render上:あなたは単一目的のものに分割コンポーネントに思考の正しい道にある

render() { 
    return (
    <div> 
     <h2>Comments List</h2> 
     {this.state.users.map((user, index) => <User key={index} user={user} />} 
    <div> 
) 
} 
関連する問題