React - 通过功能组件传递支撑组件树

React - passing props up components tree through functional components

提问人:Chris 提问时间:6/1/2020 最后编辑:Chris 更新时间:6/2/2020 访问量:1672

问:

我想在我的组件树中将一个简单的字符串、数字或布尔值传递到多个级别。从我所读到的内容来看,我需要使用回调函数来做到这一点,但我似乎无法正确理解逻辑。

这是我将道具从 Parent App 传递给孙子 Breadcrumb 的示例。我希望这个道具实际上来自树中的最后一个子项,即“ResultsPage”组件。

我意识到有更好的方法可以做到这一点(redux、上下文、不同的结构等),对我来说,这里的重点是学习和理解如何使用回调函数以及如何将一个道具传递上几个以上的级别。

新手友好 - 感谢您的任何输入:)

class App extends React.Component {
  render() {
    return (
      <>
        <h1>Top level app</h1>

        {/* I import the header and pass down prop */}
        <Header currentLocation="Results Page" />

        {/* I import the main app content */}
        <ResultsPage />
      </>
    );
  }
}

function Header(props) {
  return (
    <>
      <h2>
        This is the header element. It will have some nav items and the
        breadcrumb I import
      </h2>

      {/* I import the breadcrumb accept the props from parent and pass the props down to child */}
      <Crumbs currentLocation={props.currentLocation} />
    </>
  );
}

function Crumbs(props) {
  return (
    <>
      {/* I display the props I passed down through the tree */}
      <h3>
        <small>This is the breadcrumb, you are on</small>{" "}
        {props.currentLocation}
      </h3>
    </>
  );
}

function ResultsPage() {
  return (
    <>
      <p>
        This is the actual results content. I would like this component to tell
        the header component that I have loaded so it can update the breadcrumb
        to let it know which page is currently loaded in the app.
      </p>
    </>
  );
}

export default App;

为了完成这个问题,我提出了以下解决方案:

Codesandbox:初始问题的解决方案

Codesandbox:仅使用功能组件解决同一问题的其他解决方案

希望它能帮助下一个人:)

javascript reactjs 反应道具

评论

0赞 Josh Hunt 6/1/2020
你试过什么,为什么没有用?
0赞 Chris 6/1/2020
我花了整整 2 天的时间阅读教程和文档。我的问题是它们总是非常复杂,或者它们使用类组件,而我很难将其转换为函数组件,或者当我真的只想发送一个道具时,它们使用状态等等。当我试图理解我上面的内容时,情况也是如此:如何将道具向下传递几层。我找不到任何简单的例子。因此,我花了几天时间来浏览教程和文档,直到我能够构建您在上面看到的这个非常简单的组件树。以上帮助我理解了!

答:

1赞 edison16029 6/1/2020 #1

维护一个本地状态变量来存储位置,并通过 props 传递一个回调函数来设置它。

class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      currentLocation : "InitialLocation"
    }
  }

  changeCurrentLocation = (newLocation) => {
    this.setState({currentLocation : newLocation})
  }

  render() {
    ...
    <ResultsPage callback={this.changeCurrentLocation}/>
  }
}

changeCurrentLocation 函数将新位置作为参数并修改状态。每次状态更改时,都会再次调用 render 函数。这将使用更新的状态信息刷新视图,在本例中为 currentLocation。

function ResultsPage({ callback }) {
  useEffect(() => {
    callback('My Results');
  }, [callback])

  return (
    ...
  );
}

评论

0赞 Chris 6/1/2020
谢谢爱迪生,我试过了这个,但它抛出了错误:codesandbox.io/s/pass-props-up-wb03r?file=/src/App.js
0赞 Josh Hunt 6/1/2020
这里的初始答案有一些问题,我已经修改以修复:changeCurrentLocation 必须使用箭头函数才能在范围内保持正确,并且不应在 render 函数中调用 callback,因为这会导致无限循环(在 render 时,调用 callback 来设置状态,这会触发另一个渲染,从而导致再次调用回调, 等) codesandbox.io/s/pass-props-up-o6scl?file=/src/App.jsthis
0赞 Chris 6/1/2020
非常感谢乔希!这有效,我实际上设法弄清楚了如何使用新状态,:)我已经更新了沙盒,我将评论所有行以供我自己理解,直到我弄清楚你在那里做了什么。
0赞 edison16029 6/1/2020
谢谢你@Josh,我也是在 StackOverflow 中回答问题的新手。克里斯,如果有效,请接受答案。谢谢:)
0赞 Chris 6/2/2020
爱迪生和乔希,谢谢你们抽出时间接受采访。我接受了这个答案,但@edison,你真的应该用 Josh 的更新来更新你的版本,这样下一个阅读这篇文章的人就可以有一个工作样本。我评论了各种元素并清理了一点,可以在这里看到完整的工作答案:codesandbox.io/s/pass-state-up-and-props-down-wb03r?file=/src/......
-2赞 Sandun Isuru Niraj 6/1/2020 #2

最好的方法是这样做,因为我认为将状态保留在 redux 商店中。您可以在 redux 中使用方法创建一个侦听器,以从父组件中侦听来自子组件的任何调度。subscribe()

还有一些简单的方法,你可以使用localstorage。您可以存储子组件中的值,并使用回调方法由父组件侦听它。我希望你能理解我想说的话。window.addEventListener('storage', function(e) { }

评论

0赞 Josh Hunt 6/1/2020
这个问题在 React 中很容易用回调道具解决,而不是引入一个全新的库。此外,不建议使用 localStorage 来传播更改,因为可能很难理解这些值的保存位置,并且会中断数据的单向流。
0赞 Chris 6/1/2020
谢谢桑顿。我已经开始阅读 Redux 文档,但我认为它现在有点超出了我的范围:)