简体   繁体   English

React Hooks:在componentDidMount上调度一个动作

[英]React Hooks: Dispatch an action on componentDidMount

I have three pages, PageA, PageB and PageC , that contain a form element formField . 我有三个页面,分别是PageA,PageB和PageC ,它们包含一个表单元素formField

State in globalReducer.js globalReducer.js声明

import { fromJS } from 'immutable';

const initialState = fromJS({
  userInteractionBegun: false,
  pageActive: '',
  refreshData: true,
})

I want to dispatch an action that sets pageActive to corresponding page value(One of A, B or C ) when the component(page) mounts and refreshes formField to blank if userInteractionBegun === false . 我想调度一个操作,该操作将在组件(页面)装入时将pageActive设置为对应的页面值( A,B或C之一 ),如果userInteractionBegun === false formField刷新为空白。

For every page component, to get pageActive state in props from globalReducer , I do, 对于每个页面组件,要从globalReducer的 props获取pageActive状态,

function PageA(props) {
  //.....
}

// globalState is defined in conigureStore, I am using immutable.js. Link provided below this code.
const mapStateToProps = state => ({
  pageActive: state.getIn(['globalState', 'pageActive']),
})

export default connect(mapStateToProps, null)(PageA);

Link to immutable.js getIn() 链接到immutable.js getIn()

store.js store.js

import globalReducer from 'path/to/globalReducer';

const store = createStore(
  combineReducers({
    globalState: globalReducer,
    //...other reducers
  })
)

I want to abstract the logic to update pageActive every time a component(page) mounts. 我想抽象每次安装组件(页面)时更新pageActive的逻辑。

I know how to abstract this logic using an HOC, but I don't know how to do it using react hooks , so that every time pageA, pageB or pageC mounts, an action to setPageActive is dispatched and formField is set to blank if userInteractionBegun is false. 我知道如何使用HOC抽象此逻辑,但是我不知道如何使用react 钩子来做到这一点,因此,每次挂载pageA,pageB或pageC时setPageActive调度对setPageActive的操作,并且如果userInteractionBegunformField设置为空白是错误的。


For instance, I would do in pageA.js 例如,我将在pageA.js中

import usePageActive from 'path/to/usePageActive';

const [pageActive, setPageActive] = useReducer(props.pageActive);
usePageActive(pageActive);

Then in usePageActive.js 然后在usePageActive.js中

export default usePageActive(pageActive) {
  const [state, setState] = useState(pageActive);
  setState(// dispatch an action //)
}

I haven't had much time to dip my toes into react hooks yet, but after reading the docs and playing with it for a minute, I think this will do what you're asking. 我还没来得及投入很多时间,但是在阅读了文档并玩了一会儿之后,我认为这可以满足您的要求。 I'm using built-in state here, but you could use redux or whatever else you like in the effect. 我在这里使用内置状态,但是您可以使用redux或其他任何您想要的效果。 You can see a working example of this code here The trick is using a hook creator to create the custom hook. 您可以在此处看到此代码的有效示例。诀窍是使用挂钩创建器创建自定义挂钩。 That way the parent and children can keep a reference to the same state without the useEffect affecting the parent. 这样,父级和子级可以保持对相同状态的引用,而useEffect不会影响父级。

import React, { useState, useEffect } from 'react';
import ReactDOM from "react-dom";

const activePageFactory = (setActivePage) => (activePage) => {
  useEffect(() => {
    setActivePage(activePage)
    return () => {
      setActivePage('')
    }
  }, [activePage])
  return activePage
}

function App() {
  const [activePage, setActivePage] = useState('');
  const [localPage, setLocalPage] = useState('Not Selected');
  const selectedPage = () => {
    switch(localPage) {
      case 'A':
        return <PageA useActivePage={activePageFactory(setActivePage)}  />
      case 'B':
        return <PageB useActivePage={activePageFactory(setActivePage)}  />
      default:
        return null;
    }
  }
  return (
    <div>
      <p>Active page is {activePage}</p>
      <button onClick={() => setLocalPage('A')}>
        Make A Active
      </button>
      <button onClick={() => setLocalPage('B')}>
        Make B Active
      </button>
      {
        selectedPage()
      }
    </div>
  );
}

function PageA({useActivePage}) {
  useActivePage('A');
  return (
    <div>
      <p>I am Page A</p>
    </div>
  )
}

function PageB({useActivePage}) {
  useActivePage('B');
  return (
    <div>
      <p>I am Page B</p>
    </div>
  )
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM