反应:将状态从一个组件导入到另一个组件?

时间:2018-09-21 16:23:42

标签: javascript reactjs components state

Link组件已加载到Foot组件中(在底部可见)。

我想让Content组件加载初始状态,并在用户单击适当的按钮时更改状态。

除非在同一个组件中,否则我似乎无法更改状态,但是将状态加载到ul中确实很奇怪。

链接组件

import React, { Component } from 'react';

import Home from './Home';
import Characters from './Characters';
import Plot from './Plot';
import Scenes from './Scenes';
import Notes from './Notes';

class Link extends Component {
  constructor() {
    super();
    this.state = {page: <Home />}
  }

  loadPage = (page) => {
    this.setState({page: page})
  }

  render() {
    const links = [
      {
        title: 'Home',
        page: <Home />
      }, 
      {
        title: 'Characters',
        page: <Characters />
      }, 
      {
        title: 'Plot',
        page: <Plot />
      }, 
      {
        title: 'Scenes',
        page: <Scenes />
      }, 
      {
        title: 'Notes',
        page: <Notes />
      }
    ]

    const link = links.map((item, index) => {
      return (
        <li key={index}>
          <button onClick={() => this.loadPage(item.page)}>
            {item.title}
          </button>
        </li>
        )
    })
    return (
      <ul className="Link">
        {link}
      </ul>
    );
  }
}

export default Link;

内容组件

import React, { Component } from 'react';

import Link from './Link';

class Content extends Component {

  render() {
    return (
      <div className="Content">
        {/*this.state.page goes here*/}
      </div>
    );
  }
}

export default Content;

英尺组件(无关紧要,但是常规链接会在此处

import React, { Component } from 'react';

import Link from './Link'

class Foot extends Component {

  render() {
    return (
      <footer className="Foot">
        <Link />
      </footer>
    );
  }
}

export default Foot;

3 个答案:

答案 0 :(得分:0)

如果您使用的是最新的React版本,则可以使用React上下文来传递数据。

const {Provider, Consumer} = React.createContext(defaultValue);

在链接组件中使用提供程序。

<Provider value={/* some value */}>

在内容组件中使用使用者。

<Consumer>
  {value => /* render something based on the context value */}
</Consumer>

有关更多详细信息,请参阅官方文档。 https://reactjs.org/docs/context.html#reactcreatecontext

答案 1 :(得分:0)

React就是关于数据在应用程序流中的流动。 Wich表示您的组件具有自己的状态,或者通过props从父组件接收状态。您需要的是容器之间的水平数据流。将您的组件包装在父组件中,或者使用React中的references

答案 2 :(得分:0)

您将需要使用Props将被点击的链接推送到父链接。 因此,对于以下示例,我假设内容将是父组件。

import React, { Component } from 'react';

import Home from './Home';
import Characters from './Characters';
import Plot from './Plot';
import Scenes from './Scenes';
import Notes from './Notes';

class Link extends Component {
  // this.props.menuClicked(item.page) 
  // hits the menuClicked props of Foot Component
  render() {
    return (
      <ul className="Link">
        {links.map( (item, index) => {
          return (
            <li key={ index }>
              <a href="#" onClick={ () => this.props.menuClicked(item.page) }>
                { item.title }
              </a>
            </li>
          )
        })}
      </ul>
    );
  }
}

export default Link;

而Foot组件是Link Component的父代。

import React, { Component } from 'react';
import Link from './Link'
class Foot extends Component {
  constructor() {
    super();
    this.loadPage = this.loadPage.bind(this)
  }

  loadPage = (page) => {
    // notice this also pushes the page clicked up to the parent component which is 
    // the Content Component
    this.props.changePage(page);
  }

  render() {
    return (
      <footer className="Foot">
        <Link menuClicked={ () => this.loadPage(page) } />
      </footer>
    );
  }
}

export default Foot;

并且主要的父级(链接组件的祖父母)将成为内容组件。

// Content
import React, { Component } from 'react';
import Footer from './Footer';
import Home from './Home';
import Characters from './Characters';
import Plot from './Plot';
import Scenes from './Scenes';
import Notes from './Notes';
import Link from './Link';

class Content extends Component {
  constructor() {
    super()
    // default page
    this.state = { page: 'Home' }
    this.changePage = this.changePage.bind(this);
  }
  // called everytime the Link is clicked
  changePage(newPage) {
    this.setState({
      page: newPage
    })
  }

  render() {
    const links = [
      {
        title: 'Home',
        page: <Home />
      }, 
      {
        title: 'Characters',
        page: <Characters />
      }, 
      {
        title: 'Plot',
        page: <Plot />
      }, 
      {
        title: 'Scenes',
        page: <Scenes />
      }, 
      {
        title: 'Notes',
        page: <Notes />
      }
    ];
    let contentToLoad = null,
      pageToLoad = this.state.page;
    links.forEach( (item) => {
      if (item.title == pageToLoad) {
        contentToLoad = item.page;
      }
    });

    return (
      <div className="Content">
        { contentToLoad }
        <Footer changePage={ this.changePage } />
      </div>
    );
  }
}

export default Content;

基于在链接组件中单击的链接,相应的内容将被加载到内容组件中。如您所见,Foot Component只是传递了Link Component推送到Content Component的内容,您可以完全取消Foot Component,也可以使用@ShubamGupta提出的方案,即使用Context API。 借助ContextAPI,您可以拥有一个提供者和一个使用者,并且如果您遵循他发送的链接,您将能够直接将内容从链接组件传递到内容组件。