2017-01-13 1 views
1

Я изучаю React с использованием JSX и ES6, и у меня есть довольно приличная ручка о том, как создавать компоненты и направлять их на разные виды с помощью ReactRouter4.Как вводить данные в один компонент React и визуализировать его в другом?

Что я до сих пор не смог выяснить, например, как создать страницу администратора, где я введу детали работы для своего портфолио и выполнить все работы на другой странице, предположительно на странице Портфолио ,

Вот что у меня есть.

App.js загружает 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; 

Portfolio.js компонент имеет конструктор, чтобы связать уникальный метод с именем addWork(), РЕАКТ методы componentWillMount() и componentWillUnmount() для обработки состояния, и по умолчанию render(). Еще одна вещь, которая стоит упомянуть об этом компоненте, заключается в том, что он вызывает компонент под названием ../base, который имеет все подробности в онлайн-БД через Firebase. Поэтому, если это имеет значение, где это место, тогда учтите это, иначе не потейте.

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; 

Внутри Object я картографирование через Work компонента, который является только элементом списка, я сделал еще один компонент для и не очень актуален в этом вопросе.

И наконец, у меня есть компоненты Admin.js и AddWorkForm.js. Я отвлек AddWorkForm.js, чтобы использовать его в другом месте, если это необходимо, в основном основная идея React Components, поэтому я решил сделать это именно так.

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; 

и AddWorkForm.js компонент, который является в основном формой, которая onSubmit создает объект и восстанавливает виде

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; 

Вот файл, который включает в себя, где я использую :

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')); 

Итак, вот что я пробовал и не смог выполнить, и это, скорее всего, какое-то решение this.props, которого я не был способный определить, мне нужно создать work в компоненте Admin.js, который создает объект, а затем запустил этот объект для компонента Portfolio.js, чтобы он мог визуализировать его через компонент Work.js и он не добавляет объект в базу данных.

Это работает, когда я помещаю все компоненты на одну страницу, что не идеально, потому что тогда любой доступ к моему портфолио может добавить работу. Конечно, я мог бы начать процесс обучения аутентификации и как заставить этот компонент появляться или исчезать на основе учетных данных пользователя, но я бы скорее изучил очень ценный навык, чтобы иметь возможность иметь мою страницу администратора на отдельном представлении вместе, Я вижу еще одно приложение для изучения этого.

Хотелось бы услышать мнение других об этом и где они могут определить, что я здесь не сработал.

Btw, я понимаю, что у меня есть другие компоненты, такие как Nav.js и Title.js, но они не нужны, чтобы проиллюстрировать пример.

спасибо.

+4

TLDR. Вы не можете обмениваться данными между двумя компонентами, которые находятся на одном уровне или в разных ветвях. Вам нужен либо родительский компонент, который хранит их, либо что-то вроде Redux. – zurfyx

+0

Эхо, что говорит @zurfyx. Сохранение состояния в родительском компоненте Admin и Portfolio, вероятно, является хорошим первым подходом. Из любопытства, вы на самом деле используете какой-либо маршрутизатор? Можете ли вы показать код, в котором находятся ваши компоненты Match? – azium

+0

@zurfyx Хорошо, я посмотрю на это. – MARS

ответ

0

Вы можете передавать компоненты в качестве реквизита, а при использовании React Router вы можете использовать named components.

Для совместного использования данных между братьями и сестрами лучше иметь данные о родительском компоненте, хотя вы можете использовать контекст, но этот is not advised и может быть неприемлем для будущих версий.

Если вам нужно создать что-то на другом компоненте (не знаю почему), вы можете передать функцию, которая будет ее отображать.

Смежные вопросы