我正在使用反应和电子构建桌面应用程序。由于它增长迅速,我意识到我需要某种状态管理,如Redux,以避免在组件之间传递许多属性。我开始阅读Redux官方留档,但仍然不知道如何在我的情况下实现它。我卡住了!
例如,我有一个呈现许多子组件的主App
组件。其中一个有按钮。点击后,它应该向商店发送一个“事件”,以便主应用
可以执行相应的操作。我怎样才能做到这一点?我找不到事件的概念,我已经在如何开始使用Redux上碰壁了。
为什么会发生这样的事件?因为在这种情况下,发送一个动作并修改应用程序状态对我来说是愚蠢的。我只想通知根组件根据用户操作分派操作。例如,用户与一个表示组件交互,该组件应该告诉容器组件进行API调用或开始捕获音频/摄像机。
据我所知,到目前为止,实现这一点的唯一方法是改变状态,使另一个侦听更改的组件检测到一个表示“嘿,让我们这样做吧”的特殊值,然后再次改变状态,说“嘿,我正在这样做”,当它完成时,状态再次改变为“嘿,它完成了”。
谁能告诉我正确的方向?
值得一提的是,我遇到了一个类似的问题(单击树中其他位置的按钮,使地图重置其视口),并用一个简单的增量键解决了这个问题。
按钮调度动作:
export const RESET_MAP = "RESET_MAP";
export const resetMap = () => {
return {
type: RESET_MAP,
};
};
在减速器中:
case RESET_MAP:
return Object.assign({}, state, {
setvar: state.setvar + 1
});
在地图中:
static getDerivedStateFromProps(newProps, state) {
var newState = null;
if (newProps.setvar !== state.setvar) {
newState = {
setvar: newProps.setvar,
[other magic to reset the viewport]
}
}
return newState;
你认为它看起来很傻的原因是因为你不想让你的表现组件知道重复使用吗?如果是这样,则mapDispatchToProps
和bindActionCreators
可能有助于整理,例如:
// App.js
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { someAction } from './actions';
import Button from './Button';
const App = ({ onButtonClick }) => (
<div>
Hello.
<Button onClick={onButtonClick}>Click me.</Button>
</div>
);
export default connect(null, dispatch => {
return bindActionCreators({
onButtonClick: someAction
}, dispatch);
})(App);
// Button.js
import React from 'react';
export default Button = ({ onClick, children }) => <button onClick={onClick}>{children}</button>;
您可以看到只有连接的容器组件知道该操作,按钮(甚至应用程序)不知道单击会触发操作。
例如,用户与一个表示组件交互,该组件应该告诉容器组件进行API调用或开始捕获音频/摄像机。
也许您的容器组件做得比它应该做的更多。考虑这样一种情况:React组件只做两件事:
如果您没有使用redux,并且希望在单击按钮时进行API调用,则可能类似于:
class App extends Component {
state = { data: {} }
makeAPICall() {
fetch(url).then(data => this.setState({ data }))
}
render() {
<Child
data={this.state.data}
makeAPICall={this.makeAPICall}
/>
}
}
let Child = ({ data, makeAPICall }) => (
<button onClick={makeAPICall}>Call API!</button>
)
App
组件负责存储全局状态和处理事件,但我们必须通过组件树传递该状态和应用程序的处理程序,很可能是通过本身永远不会使用这些道具的组件。
通过添加Redux,您的应用程序现在可以更好地处理API调用或打开摄像头等副作用。中间件!
让这个(蹩脚的)插图帮助你:
因此,现在您的App
组件可以像所有其他组件一样只是一个普通的表示组件,只需根据存储道具显示数据,并在需要时处理任何用户输入/调度操作。让我们使用thunk
中间件更新上面的示例
// actions.js
export let makeAPICall = () => {
return dispatch => {
fetch(url).then(data => dispatch({
type: 'API_SUCCESS',
payload: data,
})).catch(error => dispatch({ type: 'API_FAIL', payload: error }))
}
}
// Child.js
import { connect } from 'react-redux'
import { makeAPICall } from './actions'
let Child = ({ dispatch }) => (
<button onClick={() => dispatch(makeAPICall())}>Call API!</button>
)
export default connect()(Child)
以这种方式思考React应用程序非常强大。关注点的分离安排得很好。组件显示内容并处理事件。中间件处理任何副作用(如果需要的话),并且存储仅仅是一个对象,它将导致React在数据更改时重新渲染。
更新:"模态问题"
React应用程序可能有一些全局内容,如模态和工具提示。不要考虑“开放模态”事件...想想“当前模态内容是什么?”。
模态设置可能看起来是这样的:
// modalReducer.js
function reducer (state = null, action) {
if (action.type === 'UPDATE_MODAL') {
return action.payload
}
// return default state
return state
}
// App.js
let App = connect(state => ({ modal: state.modal }))(
props =>
<div>
<OtherStuff />
<Modal component={props.modal} />
</div>
)
// Modal.js
let Modal = props =>
<div
style={{
position: 'fixed',
width: '100vw', height: '100vh',
opacity: props.component ? 1 : 0,
}}
>
{props.component}
</div>
// Child.js
let Child = connect()(props =>
<button onClick={e =>
dispatch({
type: 'UPDATE_MODAL'
payload: <YourAwesomeModal />
})
}>
Open your awesome modal!
</button>
)
这只是一个例子,但效果会很好!当状态时。模态
为空
您的模态不透明度为0,不会显示。当您分派UPDATE_MODAL
并传入一个组件时,该组件将显示您分派的任何组件,并将不透明度更改为1,以便您可以看到它。稍后您可以分派{type:'UPDATE_MODAL',payload:null}
来关闭模式。
希望这能给你一些思考的东西!
一定要读丹的答案。他的方法类似于存储模式的“元数据”与组件本身,组件本身更适合于重现时间旅行等幻想。
问题内容: 我使用的是react-router,因此我将组件用于整个应用程序中的链接,在某些情况下,我需要根据用户输入动态生成链接,因此需要类似的内容 ,但无需刷新页面。 我发现了这个小笔记-(https://github.com/rackt/react- router/issues/835 )-我尝试使用,但是上下文有问题… 这导致我(https://github.com/rackt/react
我是相当新的Reactor(Spring5 WebClient),虽然我已经想出了如何做简单的请求和处理它的输出与地图或平面图,我现在需要做一个有点困难的任务: 我有一个无法改变的终点。 这个endpoint调用的基本签名是Get
问题内容: 我一直在这里关注ReduxJS文档:React的用法 在文档末尾提到了提供程序对象的用法,我将App组件包装在提供程序中,如下所示: 但是,这就是文档的结尾。如何在组件内提取提供商提供的商店? 问题答案: 通过组件访问商店的最佳方法是使用功能,如文档中所述。这使您可以将状态和动作创建者映射到您的组件,并在商店更新时自动将它们传递给他们。此外,默认情况下,它将作为传入。这是文档中的一个示
问题内容: 我正在尝试 在React元素上模拟,但无法弄清楚为什么它不起作用(触发时它没有反应)。 我只想使用JavaScript发布Facebook评论,但我停留在第一步(执行on 元素)。 我的代码是: 这是我尝试执行的网址: **https://www.facebook.com/plugins/feedback.php …** PS:我对React没有经验,我也不知道在技术上是否可行。这是可
问题内容: 我正在尝试使用React refs在安装时聚焦Redux-Form字段。 当我尝试时,会抛出一个错误: 当我console.log this.refs时,它通常是一个空对象,有时将’title’标识为ref,但它不是可靠的。 我是否正确使用了引用?我的代码在下面供参考。 … 问题答案: 请尝试使用回调函数设置ref: 然后使用它来获取基础的DOM节点: DOM输入元素是否包装在另一个元
我试图结合反应路由器v4,反应,和redux。因为react-router跟踪URL,所以我选择将该状态块排除在redux模型之外。 但我仍然需要一种方法来在react路由器发生路由更改时调度redux操作。哪里是最好的地方? 我的第一次尝试是将它放在react路由器链接的onClick属性中: 其思想是,当用户单击链接时,dispatchAction()将更新redux状态,然后加载相册组件。