如何在一个React组件中输入数据并将其渲染到另一个组件中?

时间:2017-01-13 22:04:24

标签: javascript reactjs ecmascript-6 react-jsx

我正在学习使用JSX和ES6的React,我对如何使用ReactRouter4创建组件和路由到不同视图有了相当不错的处理。

我仍然无法弄清楚的是,例如我如何创建一个管理页面,我在其中输入我的投资组合的工作细节,并将所有工作渲染在另一个页面上,可能是投资组合页面。

这就是我所拥有的。

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()的唯一方法,React方法componentWillMount()componentWillUnmount()来处理状态,默认{{1} }。关于这个组件还有一点需要注意的是,它正在调用一个名为render()的组件,该组件通过Firebase将所有详细信息提供给在线数据库。因此,如果这与它所处的位置相关,那么请考虑到这一点,否则不要冒汗。

../base

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.jsAddWorkForm.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;

这是包含我正在使用ReactRouter的地方的文件:

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 1}} component,它创建对象,然后将该对象抛出到Portfolio.js组件,以便它可以通过Work.js组件呈现它,并且它不会将对象添加到DB。

当我将所有组件放在同一页面上时这是有效的,这是不理想的,因为访问我的投资组合的任何人都可以添加作品。当然,我可以开始学习身份验证的过程以及如何根据用户凭据使该组件显示或消失,但我更愿意学习能够将我的管理页面放在一个单独的视图中的非常有价值的技能,因为我看到另一个学习这样做的应用程序。

很想听到别人对此的看法以及他们可能在哪里确定我在这里失败。

顺便说一句,我知道我有其他组件,例如Nav.jsTitle.js,但为了说明这个例子,它们不是必需的。

谢谢。

1 个答案:

答案 0 :(得分:0)

您可以将组件作为道具传递,使用React Router时可以使用named components

对于兄弟姐妹之间的数据共享,最好建议将数据放在父组件上,尽管您可以使用上下文,但是这个is not advised可能在将来的版本中无法使用。

如果你需要在另一个组件上创建一些东西(不知道为什么),你可以传递一个可以渲染它的函数。