我有三个页面,PageS,PageS和PageS,它们包含表单元素formField
。
globalReducer.js中的状态
import { fromJS } from 'immutable';
const initialState = fromJS({
userInteractionBegun: false,
pageActive: '',
refreshData: true,
})
我想调度一个动作,当组件(页面)安装时,将pageActive
设置为相应的页面值(A,B或C中的一个),如果formField
,则将userInteractionBegun === false
刷新为空白。
对于每个页面组件,要从globalReducer获取pageActive
中的props
状态,我这样做,
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);
store.js
import globalReducer from 'path/to/globalReducer';
const store = createStore(
combineReducers({
globalState: globalReducer,
//...other reducers
})
)
我想抽象逻辑来在每次组件(页面)安装时更新pageActive
。
我知道如何使用HOC来抽象这个逻辑,但我不知道如何使用react hooks来做,所以每次pageA,pageB或pageC安装时,调度setPageActive
的动作,如果formField
,userInteractionBegun
被设置为空白是假的。
例如,我会在pageA.js中进行
import usePageActive from 'path/to/usePageActive';
const [pageActive, setPageActive] = useReducer(props.pageActive);
usePageActive(pageActive);
然后在usePageActive.js中
export default usePageActive(pageActive) {
const [state, setState] = useState(pageActive);
setState(// dispatch an action //)
}
我没有太多时间将脚趾浸入反应钩中,但在阅读完文档并使用它一分钟之后,我认为这样做会有所帮助。我在这里使用内置状态,但你可以在效果中使用redux或其他任何你喜欢的东西。你可以看到这个代码的工作示例here诀窍是使用钩子创建器来创建自定义钩子。这样,父级和子级可以保持对同一状态的引用,而不会影响父级的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>
)
}