2017-10-02 4 views
0

Ich versuche, die Best Practices von ReactJS bei der Verwendung von Zustandskomponenten zu befolgen, wenn Statusänderungen möglich sind, und repliziert, wenn eine Komponente zustandslos ist, aber ich weiß nicht, wie ich das soll Strukturiere meine Komponenten, um beide Typen zuzulassen. Derzeit hole ich eine JSON-Datei und setze die einzelnen Objekte in einer Zustandskomponente und dann möchte ich das Design und Layout dieser Informationen mit individuellen Propkomponenten für jede Information strukturieren, was meiner Meinung nach die beste Vorgehensweise ist, aber die Prop-Komponenten geben Fehler aus, dass die übergebene Eigenschaft undefined ist. Ist dies ein Eltern/Kind-Problem?ReactJS - Rückgabeobjekt vom Status an Prop übergeben

Hier ist meine Ansicht Feed (Top-Level, gemacht zu werden):

export default class CommentFeed extends React.Component { 

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

meine damaligen und als Staat Komponente gesetzt Abruf:

//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> 
     ) 
    } 
}; 

Und hier ist die <UserTitle /> prop komponente:

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

Ich würde das gerenderte Zeug wahrscheinlich nicht im Zustand speichern? Das gibt dir einen ziemlich aufgeblähten Zustand. Stellen Sie den Status als Ergebnis Ihres Async ein und führen Sie das Rendern im Rendering durch. Sie können die .map von this.state.users direkt in die Render-Funktion oder in eine Sub-Render-Methode einfügen. Bei Komponenten können Sie immer null zurückgeben. Wenn also keine Prop-Komponente bereitgestellt wird, geben Sie einfach null in der Render-Funktion zurück. – thsorens

+0

es ist {this.props.title} nicht {props.title} auch ich denke render hat keine Parameter – Mahmoud

+0

Ich war dabei, das gleiche zu erwähnen. Render hat keine Params, Sie müssen sich darauf beziehen – thsorens

Antwort

3

Sie sind auf der rechten Art des Denkens auf eine Aufteilung der Komponenten zu einzweckmaschinen diejenigen .

Im Allgemeinen in der "Gemeinschaft" wir in der Regel zwei Arten von Komponenten:

  • Container Komponenten
  • Ansicht Komponenten (dumb Komponenten)

Container Komponenten sollten die Geschäftslogik verarbeiten, Daten, Aktionen usw. abrufen und dann die benötigten Daten als Props an die View-Komponenten übergeben.

Komponenten anzeigen, nicht mit Daten umgehen, nicht abrufen, nur die Ansicht anzeigen.meist nicht, daß sie sogar ihren eigenen Staat haben (nicht immer)

So, hier ist eine kurze Ansicht von dem, was Sie haben müssen: - CommentsContainer - CommentsFeedView - CommentView

, wie es im Code aussehen grundsätzlich sollte :

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> 
    ) 
} 

Wenn Sie verschachtelte Karten erstellen möchten, müssen Sie Ihre Denkweise ändern. Stellen Sie sich eine Komponente als eine schwarze Box vor, die Inhalt rendert. Es kann komplexere Komponenten und weniger geben. Komponenten, die andere Komponenten und Liner darstellen.

So ist dies ein Beispiel wie die Frage Code, den Sie haben:

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> 
     ) 
    } 
} 

wie Sie hier sehen können, wir über die Karten nicht wirklich, oder verschachtelte Karten. Jede Komponente rendert sich selbst und kümmert sich nicht um das "Äußere"

+0

erhalten Dies ist eine großartige Erklärung und vielen Dank für deine Hilfe! – cphill

+0

Ist es möglich, ein schnelles Beispiel dafür zu geben, wie eine verschachtelte Karte in der Komponente "CommentsFeedView" aussehen würde? Wie Sie vielleicht in meiner Frage bemerken, ist der Kommentarbereich eine Karte innerhalb der Benutzerkarte – cphill

+0

Sicher, also nur eine Liste von Kommentaren und darin eine Liste von Kommentaren dieser Kommentare. Wird später aktualisiert –

0

Es scheint, dass UserTitle und <ul>{user.user_comments.map(...)}</ul> Teil derselben User Komponente sind (Name wie Sie wünschen).

Anstatt Komponenten innerhalb eines Callbacks zu rendern (nicht empfohlen, da Sie Komponenten in den Status speichern), besteht mein Vorschlag darin, eine einzelne Komponente zu erstellen, die alle Benutzerdetails berücksichtigt.

Es hält Ihren Code und Komponenten wiederverwendbar (UserTitle zum Beispiel) und testbar, ganz zu schweigen von müssen Sie die große then(data =>...) Geschäftslogik jedes Mal aktualisieren, wenn der Benutzer irgendwie ändern muss.

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> 

auf fetchList Sie Benutzer Array auf Zustand speichern:

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

und auf render:

render() { 
    return (
    <div> 
     <h2>Comments List</h2> 
     {this.state.users.map((user, index) => <User key={index} user={user} />} 
    <div> 
) 
} 
Verwandte Themen