在我的React应用程序中,我有一个包含应用程序的整个状态和用于修改状态的函数的主组件。
为了访问所有子组件中的状态和功能,我通过子组件属性(app
)从主组件传递this
:
class App extends React.Component {
state = DefaultState;
funcs = getController(this);
render() {
return (
<Header app={this} />
<Page app={this} />
<Footer app={this} />
)
}
}
function getController(app: App) {
return {
switchPage: (page: string) => {
app.setState({ page: page });
},
}
}
因此在子组件中我可以访问状态变量并像这样修改它们:
const HeaderComponent: React.FC<CompProps> = (props) => {
return (
<div>
<h1>{props.app.state.currentPage}</h1>
<button onClick={(e) => {props.app.funcs.switchPage('home')}}>Home</button>
</div>
)
}
这是我为全局状态找到的最快/最简单的解决方案。然而,我从来没有在任何教程中看到过这种情况。我想主要的问题是,当一个值在全局状态下改变时,整个应用程序都会渲染,但React Context API也是如此。
问题是,这种方法是否有任何缺点或不使用它的理由?
您可以将func
保存到导出的let变量中,并在不重新渲染的情况下使用func
的最新版本,但由于这不是常见的情况,因此您不会找到关于它的太多信息。因为它只是简单的javascript,任何已知的hack都可以工作。此外,你关于反应-上下文重新呈现的部分问题是正确的,尽管你必须考虑到它将重新呈现,并且它将被更多地修剪以优化未修改的兄弟。
你也可以为这些组件提供一个简单的ref (useRef
),这将允许它们访问func
的最新版本,但是因为ref引用本身在重新呈现页面时不会改变,所以它们不会因为功能改变而更新。
我使用react功能组件,但类基可能是如此相似
export let funcs = null
const App = () => {
funcs = getController();
render() {
return (
<Header />
<Page />
<Footer />
)
}
}
// header component
import { funcs as appFuncs } from '~/app.js'
const HeaderComponent: React.FC<CompProps> = (props) => {
return (
<div>
{/* same thing can be happened for the state */}
<button onClick={(e) => {appFuncs.switchPage('home')}}>Home</button>
</div>
)
}
<<p>钩子版本/strong>const App = () => {
const ref = useRef();
funcs = getController();
ref.current = {state, funcs};
// note ref.current changes not the ref itself
render() {
return (
<Header app={ref} />
<Page app={ref} />
<Footer app={ref} />
)
}
}
// header
const HeaderComponent: React.FC<CompProps> = (props) => {
return (
<div>
<h1>{props.app.current.state.currentPage}</h1>
<button onClick={(e) => {props.app.current.func.switchPage('home')}}>Home</button>
</div>
)
}
如有任何建议或其他技巧,我将不胜感激。