在React中将道具从父级传递给同级

时间:2020-04-22 00:25:42

标签: reactjs react-router

我正在重新创建一个已经在Angular中创建的简单React应用。 React应用程序包含两个组件:一个(menus.js)用于侧面菜单,第二个(content.js)在单击每个链接时将显示菜单中每个项目的内容(就像各种iframe)。在App.js中,我正在进行REST API调用以填充menus.js组件的状态。请注意,这两个组件都在App.js中,如下所示:

App.js

import React,{Component} from 'react';
import Menus from './components/menus';
import Content from './components/content';

class App extends Component {

  state = {
    menus: []
  }

  componentDidMount(){
    fetch('api address')
    .then(res => res.json())
    .then((data)=> {
      this.setState({menus: data})
    })
    .catch(console.log)
  }

  render(){
  return (
    <div>
      <div><Menus menus={this.state.menus} /></div>
      <div><Content /></div>
    </div>
  );
}
}

export default App;

这是menu.js组件;它需要来自App.js的道具(菜单),并使用其中的项目构建菜单链接:

import React from 'react';
import { BrowserRouter as Router, Link,} from "react-router-dom";
  const Menus = ({ menus }) => {
    return (
      <Router>
        <div>
          <center><h1>Lessons</h1></center>
          {menus.map(menu => (
            <li key={menu.lesson}>
              <Link to={`/lesson/${menu.lesson}`}>{menu.lessonName}</Link>
            </li>
          ))}
        </div>
      </Router>
    );
  };
  export default Menus;

这是我需要的-如何将项目从同一道具(从App.js)传递到内容组件?仅供参考-每次单击menu.js菜单中的链接时,我都需要这样做(这就是为什么在列表中使用键的原因。简单的想法是,每次菜单时内容都会在内容组件中更新单击菜单组件中的链接。

**content.js**

import React from 'react'

const Content = () => {
  return (
    <div>{menu.content}</div>
  )
};

export default Content

3 个答案:

答案 0 :(得分:0)

在您的menu.js中,将menu对象附加到Link

...
{menus.map(menu => (
    <li key={menu.lesson}>
        <Link to={{
          pathname: `/lesson/${menu.lesson}`,
          state: menu
        }}> {menu.lessonName} </Link> 
    </li>
))}
...

在您的content.js中收到这样的menu

import React from 'react'

const Content = () => {
  console.log(props.location.state.menu.content);
  return (
    <div>{props.location.state && props.location.state.menu.content }</div>
  )
};

export default Content

了解更多here

答案 1 :(得分:0)

根据您对问题的描述以及您对所写内容的了解,在我看来,您似乎正在尝试构建一个应用程序,该应用程序可保留菜单,但是内容会根据菜单单击次数而变化。对于简单的应用程序,这就是我将其结构不同的方式。

<ParentmostComponent>
  <MenuComponent someProp={this.state.some_data} />
      <Switch>
        <Route path={"/path"} render={(props) => <Dashboard {...props} someProp={this.state.some_other_data_from_parents} />
      </Switch>
</ParentMostComponent>

这将使菜单无论内容在做什么都始终保持在那里,并且您也不必将菜单属性传递给两个组件。

答案 2 :(得分:0)

您的示例使用了反应路由器,因此此答案也使用了它。

首先,将RouterMenus上移到App,以使路由器道具可用于所有组件。然后将您的Content包装在Route中以有条件地进行渲染(即,如果路径匹配"/lesson/:lesson"):

class App extends Component {
  state = {
    menus: [
      {
        lesson: '61355373',
        lessonName: 'Passing props from parent to sibling in React',
        content: 'I am recreating a simple React app…'
      },
      {
        lesson: '27991366',
        lessonName: 'What is the difference between state and props in React?',
        content: 'I was watching a Pluralsight course on React…'
      }
    ]
  }

  render() {
    const { menus } = this.state

    return (
      <Router>
        <div>
          <div><Menus menus={menus}/></div>
          <Route path="/lesson/:lesson" render={({ match }) => (
            <div><Content menu={menus.find(menu => menu.lesson === match.params.lesson)}/></div>
          )}>
          </Route>
        </div>
      </Router>
    )
  }
}

render prop的帮助下,您可以在呈现子组件之前访问路由器道具(在本例中为match.params.lesson)。我们使用它们将所选菜单传递到Content。完成!

注意:在兄弟姐妹之间传递道具的基本技巧(没有反应路由器 Redux 等)是lift the state up