为什么不从动作创建者redux直接调度到商店?

时间:2018-09-20 22:24:38

标签: reactjs redux react-redux redux-thunk

我正在使用redux和react-native构建应用程序。

我对我使用的图案感到好奇。我没有遇到任何缺点,但是我在任何教程中都没有看到它,这让我想知道为什么没人这样做。

而不是像

那样将动作创建者作为道具传递给connect函数
 connect(mapStateToProps,{ func1, func2 })(Component);

我将应用商店导入了模块内部,首先在其中声明了功能:

import { AppStore } from '../App';
const actionCreator = () => {
   doSomethng();
   appStore.dispatch({ type: 'Action' });
};

这对我来说使执行异步操作更加容易,因为我不需要中间件:

import { AppStore } from '../App';
const actionCreator = async () => {
   await doSomethng();
   appStore.dispatch({ type: 'Action' });
};

我这样做是因为js-lint错误'no-shadow'。这让我意识到,要使用它,我必须将动作创建者导入组件文件中,然后将其作为道具传递给connect函数,以便动作创建者可以访问派发。

import { actionCreator1, actionCreator2 } from './actionCreators';

const myComponent = (props) => {
   const { actionCreator1, actionCreator2 } = props; //shadowed names
   return (
      <Button onPress={actionCreator1} />
   );
};

export default connect({}, { actionCreator1, actionCreator2 })(myComponent)

在我的版本中,我只导入一次,但不通过它进行连接。这样就无需隐藏名称。

import { actionCreator1, actionCreator2 } from './actionCreators';

const myComponent = (props) => {
   return (
      <Button onPress={actionCreator1} />
   );
};

export default connect({})(myComponent)

2 个答案:

答案 0 :(得分:1)

我喜欢您尝试为自己的特定问题找到自己的解决方案。这是工程师的标志,只是在这种情况下,这不是解决方案。

我认为Redux如何教您做事的想法并不是要被规范化。您可以在您的道具上放置一个调度程序,因为它可以使事物透明化,这意味着事物可以绑定到类之外并被注入。您已经通过直接在其他一些文件中引用隐藏了商店的依赖关系。您的应用程序在工作流程方面的工作方式不再是显而易见的。另一个反应开发人员会感到困惑,我认为这是主要缺点。

如果您对这些方面都满意,那么您所做的一切就很好。很好,它可以完成工作,但不能接受“ {fine”,因为它包含Single Responsibility Principle

之类的概念

答案 1 :(得分:0)

那么,为什么不像执行其他操作一样直接在组件内部调用操作创建者,而不将其传递给connect()函数呢?

Redux不会在您调用动作创建者时自动检测到。

Redux不会自动检测到返回操作对象的函数。

我的actions/index.js文件包含我的动作创建者。您和我都将此功能称为动作创建者,但客观地说,它只是一个功能。这就是Redux所看到的。 Redux不知道这个特定功能是一个动作。

因此,当您进入组件并导入动作创建者时,就像这样:import { selectSong } from ‘../actions’;

客观地讲,我们不是将动作创建者导入组件,从技术上讲,我们只是导入函数。

您可以整天在组件内部调用动作创建者,但这将被视为正常的JavaScript函数调用,它将返回一个对象,也就是它。

返回的对象将不会转发到redux。如果我们想确保某个动作进入减速器,则必须将其传递给该调度函数。

这是一个更直接的示例:

const store = createStore(ourDepartments);

store.dispatch(createPolicy('Alejandra', 35));

store.dispatch(createPolicy('Ben', 20));
store.dispatch(createPolicy('Daniel', 78));

store.dispatch(createClaim('Alejandra', 120));
store.dispatch(createClaim('Ben', 50));

store.dispatch(deletePolicy('Daniel'));

console.log(store.getState());

请注意,每次我分派动作时,我都会调用一个动作创建者,该动作创建者返回一个直接传递给store.dispatch()函数的动作对象。

如果我没有将那些动作创建者的结果传递给调度函数,而是简单地调用:

createPolicy('Alejandra', 35), 
createClaim('Alejandra', 120), 
deletePolicy(‘Alejandra’) 

这将永远不会更新redux存储,它将返回一个动作,但是它永远不会发送到redux中,并且它们也永远不会落入reducer中。

为确保动作创建者实际上更新了我们的状态,我们必须采取返回的动作并将其传递给我们的调度功能。

现在,当然,在我们的组件中没有对调度功能的引用。那么怎么回事?

当我们将动作创建者传递到connect()函数中时,connect()函数对action对象内部的函数执行特殊操作

export default connect(mapStateToProps, { selectSong })(SongList);

connect()函数实际上将动作包装到一个新的JavaScript函数中。当我们调用新的JavaScript函数时,connect()函数将自动调用我们的动作创建者,执行返回的动作,并自动为我们调用dispatch()函数。

因此,通过将动作创建者传递到connect()函数中,每当我们调用添加到props对象中的动作创建者时,该函数将自动执行要返回的动作并将其扔到调度函数中为我们。

因此,所有发生在幕后的事情,而在使用connect()函数时,您不必真正考虑。

这就是为什么工程师将我们的动作创建者传递给connect()函数的原因,而不是直接从组件内部直接调用它。

因此,每当您想从组件中调用动作创建者时,总会把它传递给此connect函数,而不是仅仅在组件内部任意调用它。

希望这是有道理的。