2017-01-13 3 views
1

Ich lerne Reagieren mit JSX und ES6 und ich habe eine recht anständige Handhabe für das Erstellen von Komponenten und Routen zu verschiedenen Ansichten mit ReactRouter4.Wie kann man Daten in eine React-Komponente eingeben und in einer anderen rendern lassen?

Was ich noch nicht herausfinden konnte, ist zum Beispiel, wie ich eine Admin-Seite erstellen kann, wo ich die Details einer Arbeit für mein Portfolio eingeben und alle Arbeiten auf der anderen Seite, vermutlich der Portfolio-Seite, rendern lassen kann .

Hier ist, was ich habe.

App.js lädt die Komponente Portfolio.js

import React from 'react'; 

import Navigation from './Navigation'; 
import Title from './Title'; 
import Portfolio from './Portfolio'; 

class App extends React.Component { 
    render() { 
    return(
     <div className="container-fluid"> 
     <div className="container"> 
      <div className="row"> 
      <div className="col-sm-12"> 
       <Navigation /> 
       <Title title="kuality.io"/> 
       <section className="app"> 
       <Portfolio works={this.props.works} /> 
       </section> 
      </div> 
      </div> 
     </div> 
     </div> 
    ) 
    } 
} 

export default App; 

Die Portfolio.js Komponente einen Konstruktor render() eine einzigartige Methode namens addWork(), das Reagieren Methoden componentWillMount()componentWillUnmount() und zu handhaben Zustand und den Standard zu binden. Eine weitere Sache, die über diese Komponente zu erwähnen ist, ist, dass sie eine Komponente mit dem Namen ../base aufruft, die über Firebase alle Details zu einer Online-DB enthält. Also, wenn das relevant ist, wo es ist, dann nimm das in Betracht, sonst schwitze es nicht.

import React from 'react'; 

import Work from './Work'; 
import Admin from './Admin'; 
import base from '../base'; 

class Portfolio extends React.Component { 
    constructor() { 
    super(); 

    this.addWork = this.addWork.bind(this); 

    // getInitialState 
    this.state = { 
     works: {} 
    }; 
    } 
    componentWillMount() { 
    this.ref = base.syncState(`/works` 
     , { 
     context: this, 
     state: 'works' 
     }) 
    } 
    componentWillUnmount() { 
    base.removeBinding(this.ref); 
    } 
    addWork(work) { 
    // update our state 
    const works = {...this.state.works}; 
    // add in our new works with a timestamp in seconds since Jan 1st 1970 
    const timestamp = Date.now(); 
    works[`work-${timestamp}`] = work; 
    // set state 
    this.setState({ works }); 
    } 
    render() { 
    return(
     <div> 
     <section className="portfolio"> 
      <h3>Portfolio</h3> 
      <ul className="list-of-work"> 
      { 
       Object 
       .keys(this.state.works) 
       .map(key => <Work key={key} details={this.state.works[key]}/>) 
      } 
      </ul> 
     </section> 
     </div> 
    ) 
    } 
} 

export default Portfolio; 

Innerhalb der Object ich bin Kartierung durch die Work Komponente, die nur ein Listenelement, das ich für eine andere Komponente gemacht habe und ist nicht wirklich relevant in der Frage.

Schließlich habe ich die Admin.js und AddWorkForm.js Komponenten. Ich habe die AddWorkForm.js abstrahiert, so dass ich sie woanders verwenden könnte, im Grunde die Hauptidee hinter React Components, und deshalb habe ich es so gemacht.

import React from 'react'; 

import Title from './Title'; 
import AddWorkForm from './AddWorkForm'; 

class Admin extends React.Component { 
    constructor() { 
    super(); 

    this.addWork = this.addWork.bind(this); 

    // getInitialState 
    this.state = { 
     works: {} 
    }; 
    } 

    addWork(work) { 
    // update our state 
    const works = {...this.state.works}; 
    // add in our new works with a timestamp in seconds since Jan 1st 1970 
    const timestamp = Date.now(); 
    works[`work-${timestamp}`] = work; 
    // set state 
    this.setState({ works }); 
    } 
    render() { 
    return(
     <div className="container-fluid"> 
     <div className="container"> 
      <div className="row"> 
      <div className="col-sm-12"> 
       <Title title="Admin"/> 
       <section className="admin"> 
       <AddWorkForm addWork={this.addWork} /> 
       </section> 
      </div> 
      </div> 
     </div> 
     </div> 

    ) 
    } 
} 

export default Admin; 

und die AddWorkForm.js Komponente, die im Grunde eine Form ist, dass onSubmit erstellt und Objekt und setzt das Formular

import React from 'react'; 

class AddWorkForm extends React.Component { 
    createWork(event) { 
    event.preventDefault(); 
    console.log('Creating some work'); 
    const work = { 
     name: this.name.value, 
     desc: this.desc.value, 
     image: this.image.value 
    } 
    this.props.addWork(work); 
    this.workForm.reset(); 
    } 

    render() { 
    return(
     <form ref={(input) => this.workForm = input} className="work-edit form-group" onSubmit={(e) => this.createWork(e)}> 
     <input ref={(input) => this.name = input} type="text" className="form-control" placeholder="Work Title"/> 
     <textarea ref={(input) => this.desc = input} type="text" className="form-control" placeholder="Work Description"></textarea> 
     <input ref={(input) => this.image = input} type="text" className="form-control" placeholder="Work Image"/> 
     <button type="submit" className="btn btn-primary">+Add Work</button> 
     </form> 
    ) 
    } 
} 

export default AddWorkForm; 

Hier ist die Datei, enthält, wo ich bin mit :

import React from 'react'; 
import { render } from 'react-dom'; 
// To render one method from a package user curly brackets, you would have to know what method you wan though 
import { BrowserRouter, Match, Miss} from 'react-router'; 

import './css/normalize.css'; 
import './css/bootstrap.css'; 
import './css/style.css'; 

// import '../js/bootstrap.js'; 

import App from './components/App'; 
import WorkItem from './components/WorkItem'; 
import Capability from './components/Capability'; 
import Connect from './components/Connect'; 
import NotFound from './components/NotFound'; 
import Admin from './components/Admin'; 

const Root =()=> { 
    return(
    <BrowserRouter> 
     <div> 
     <Match exactly pattern="/" component={App} /> 
     <Match pattern="/work/:workId" component={WorkItem} /> 
     <Match exactly pattern="/capability" component={Capability} /> 
     <Match exactly pattern="/connect" component={Connect} /> 
     <Match exactly pattern="/admin" component={Admin} /> 
     <Miss component={NotFound} /> 
     </div> 
    </BrowserRouter> 
) 
} 

render (<Root />, document.querySelector('#main')); 

Also hier ist, was ich versucht habe und es nicht geschafft, und es ist wahrscheinlich eine Art von this.props Lösung, die ich nicht gewesen bin in der Lage zu definieren, muss ich die work in Admin.js Komponente erstellen, die das Objekt erstellt und dann dieses Objekt auf Portfolio.js Komponente werfen, so dass es über die Komponente Work.js rendern kann und es das Objekt nicht der DB hinzugefügt.

Dies funktioniert, wenn ich alle Komponenten auf die gleiche Seite legen, was nicht ideal ist, denn dann könnte jeder, der auf mein Portfolio zugreift, eine Arbeit hinzufügen. Sicher, ich könnte den Prozess des Erlernens der Authentifizierung beginnen und wie diese Komponente basierend auf Benutzeranmeldeinformationen angezeigt oder ausgeblendet wird, aber ich würde auch lieber die sehr wertvolle Fähigkeit lernen, meine Admin-Seite in einer separaten Ansicht zusammen zu haben, weil Ich sehe eine andere Anwendung, um das zu lernen.

Würde gerne andere Meinungen dazu hören und wo sie feststellen können, dass ich hier versage.

Btw, ich weiß, ich habe andere Komponenten wie Nav.js und Title.js, aber sie sind nicht notwendig, um das Beispiel zu veranschaulichen.

Vielen Dank.

+4

TLDR. Sie können keine Daten zwischen zwei Komponenten austauschen, die sich auf derselben Ebene oder in verschiedenen Zweigen befinden. Sie benötigen entweder eine übergeordnete Komponente, die sie speichert, oder etwas wie Redux. – zurfyx

+0

Echo was @zurfyx sagt. Das Speichern des Status in einer übergeordneten Komponente von Admin und Portfolio ist wahrscheinlich ein guter erster Ansatz. Aus Neugier, verwenden Sie eigentlich Reagieren Router irgendwo? Können Sie den Code anzeigen, in dem sich Ihre Match-Komponenten befinden? – azium

+0

@zurfyx Ok, ich schaue mal rein. – MARS

Antwort

0

Sie können Komponenten als Requisiten übergeben und wenn Sie React Router verwenden, können Sie named components haben.

Für die gemeinsame Nutzung von Daten zwischen Geschwistern ist es besser, die Daten auf einer übergeordneten Komponente zu haben, obwohl Sie kontext verwenden könnten, aber diese is not advised und möglicherweise nicht auf zukünftige Versionen.

Wenn Sie etwas auf einer anderen Komponente erstellen müssen (weiß nicht warum), könnten Sie eine Funktion übergeben, die es rendern würde.

Verwandte Themen