如何根据另一个组件的事件处理程序更新一个组件?
Posted
技术标签:
【中文标题】如何根据另一个组件的事件处理程序更新一个组件?【英文标题】:How to update one component based on event handler of another component? 【发布时间】:2019-04-01 00:49:15 【问题描述】:我的 index.js 文件中有两个组件(标题和边栏),如下所示
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import
BrowserRouter as Router,
Route
from "react-router-dom";
import './index.scss';
import './responsive.scss';
import Sidebar from './sidebar';
import Header from './header';
import Home from './home';
import Products from './products';
import Variant from './variant';
import Variety from './variety';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<Router>
<div className="wrapper">
<Header />
<Sidebar />
<div id="content">
<Route exact path="/" component=Home />
<Route path="/products" component=Products />
<Route path="/variant" component=Variant />
<Route path="/variety" component=Variety />
</div>
</div>
</Router>
, document.getElementById('root'));
serviceWorker.unregister();
我的 Header 组件中有一个按钮,我想向它添加一个 onClick 事件处理程序,因此当单击 Sidebar 组件中的侧边栏时,将会切换。 现在我的问题是我无法连接这两个组件。我什至尝试使用此链接How To Pass Events Between Components 中的建议,但问题是该事件的目标是更改子组件中定义的所有元素。 我已经阅读了有关 createPortal() 的一些内容,但建议访问组件外部的 DOM,并且由于我试图从另一个组件访问组件,因此我不确定是否应该这样做。 提前感谢您的帮助。
【问题讨论】:
【参考方案1】:为了连接组件,您应该使用存储在所有组件之间共享应用程序状态。 Redux 或类似的东西可以做到。
主要思想是您更改 Header 组件中的状态,Sidebar 将监听此状态并在需要时自行更新。
【讨论】:
【参考方案2】:有几种方法。
-
您可以使用 Redux。
使用 React 上下文 API https://reactjs.org/docs/context.html 或
您可以执行以下操作
// IN MAIN FILE
state =
sidebarOpen : false
<header toggleSidebar = this.toggleSidebar />
<sidebar sidebarOpen = this.state.sidebarOpen />
toggleSidebar()
//UPDATE STATE
this.setState(
sidebarOpen : !(this.state.sidebarOpen)
)
// IN HEADER
onButtonClick()
this.props.toggleSidebar()
IN SIDEBAR
componentWillReceiveProps(props)
//LOGIC FOR UPDATING SIDEBAR YOU WILL RECIEVE UPDATED STATE HERE
【讨论】:
【参考方案3】:首先,简单说一下这两个组件的连接。React中的数据传输建议是从父组件传递到子组件。这是Lifting State Up。所以通常使用回调来改变header的父组件并传递数据返回侧边栏。现在 redux 与 react 配合得很好。所以,只需为侧边栏设置一个状态,并在 Header 的 onClick 中绑定一个函数。然后在 onClick 中添加一些东西。像这样:
<header onClick = this.expand.bind(this) />
<sidebar sidebar = this.state.sidebar />
顺便说一句,react 为我们提供了一些传递数据的方法。例如,在组件嵌套复杂且很难找到公共父组件时使用上下文。
第二,“事件针对子组件中定义的所有元素的变化”。这个问题是因为react是如何工作的。你可以使用shouldComponentUpdate来避免它。但这里不推荐。
第三,关于React Portal,添加到React v16中,用于在父组件之外渲染子组件。这个答案很好,如果你想了解的话。How to use ReactDOM.createPortal() in React 16?。侧边栏和标题组件处于同一级别。所以我认为这不是必需的。
【讨论】:
【参考方案4】:正如大家所回答的,这些是一些很好的解决方案。但是你也提到了你的限制。您也可以尝试以下一种。
let showSidebar = true;
// Function to handle toggle
const handleClick = () =>
showSidebar = !showSidebar
renderApp()
// Make renderApp function
const renderApp = () =>
ReactDOM.render(
<Router>
<div className="wrapper">
<Header handleClick=handleClick/> // call this function onClick inside your Header component
showSidebar && <Sidebar /> // toggle the Sidebar
<div id="content">
<Route exact path="/" component=Home />
<Route path="/products" component=Products />
<Route path="/variant" component=Variant />
<Route path="/variety" component=Variety />
</div>
</div>
</Router>
, document.getElementById('root'));
;
renderApp(); // Call renderApp for the first time
serviceWorker.unregister();
【讨论】:
以上是关于如何根据另一个组件的事件处理程序更新一个组件?的主要内容,如果未能解决你的问题,请参考以下文章