React Architecture:我有一个通用的中间组件,需要渲染自定义子组件
React Architecture: I have a common middle component that needs to render custom child components
我正在制作一个使用通用网格组件的仪表板。网格有自己独立的功能,并用于应用程序的其他区域。它需要在每个网格项中渲染一个自定义组件,并且有一个活动组件也渲染一个自定义组件,这些自定义组件使用来自 Grids 父组件的函数,无论渲染它是什么,下面是我目前的做法,但我'我很确定有更好的方法。
渲染网格并向下传递组件和功能的父组件
import Grid from './common/grid'
class dashboard extends Component {
gridItemSpecificFunction() { console.log('success') }
activeFunction() { console.log('success again') }
render() {
return <Grid
CustomComponent={ CustomComponent }
ActiveComponent={ ActiveComponent }
activeFunctions={ {activeFunction} }
gridItemFunctions={ { gridItemSpecificFunction:this.gridItemSpecificFunction } }
/>
}
}
根据传递的数据呈现自定义活动和网格项目的网格
class Grid extends Component {
render() {
const {CustomComponent} = this.props
return (
<GridWrapper>
{ this.props.dynamicData.map( data => (
<GridItemWrapper>
<CustomComponent { ...data } functions={ this.props.gridItemFunctions } />
</GridItemWrapper>
) )
{ active && < ActiveComponent { ...activeData }
functions={ this.props.activeFunctions }/> }
</GridWrapper>
}
)
}
}
使用通过网格项传递的函数的自定义组件示例
class CustomComponent extends Component {
render() {
const {gridItemSpecificFunction} = this.props.functions
return (
<div onClick={ gridItemSpecificFunction }>
{ this.props.text }
<div>
}
)
}
}
你真的做得很好,当然还有另一种方法可以做到这一点,可能更好只是因为更容易修改,所以你可能应该使用 Context hook 来完成这个,所以很棒的包基于它们在 Context API Hook,所以一个很好的方法就是这个
import React, { useContext, createContext, useMemo } from 'react';
const FunctionalityContext = createContext({}); // just leave it as empty state
// create a hook that return the context function
const useGridFunctions = () => {
const functions = useContext(FunctionalityContext);
return functions;
};
const CustomComponent = () => {
const functions = useGridFunctions();
return (
<div>
<button onClick={functions.gridItemSpecificFunction}>I am a custom component</button>
</div>
);
}
const ActiveComponent = () => {
const functions = useGridFunctions();
return (
<div>
<button onClick={functions.activeFunction}>I am a active component</button>
</div>
);
}
const ParentGrid = ({ functions }) => {
const functions = useMemo(() => functions, [functions]);
// the pass functions object to our context provider to get accesso through dom tree
return (
<FunctionalityContext.Provider value={functions}>
<Grid
CustomComponent={CustomComponent}
ActiveComponent={ActiveComponent}
/>
</FunctionalityContext.Provider>
);
}
如您所见,您仍然保持代码几乎相同,但您添加了一个额外的层来存储组件将使用的功能,因此 Context Api 将帮助您实现这一目标随心所欲
我正在制作一个使用通用网格组件的仪表板。网格有自己独立的功能,并用于应用程序的其他区域。它需要在每个网格项中渲染一个自定义组件,并且有一个活动组件也渲染一个自定义组件,这些自定义组件使用来自 Grids 父组件的函数,无论渲染它是什么,下面是我目前的做法,但我'我很确定有更好的方法。
渲染网格并向下传递组件和功能的父组件
import Grid from './common/grid'
class dashboard extends Component {
gridItemSpecificFunction() { console.log('success') }
activeFunction() { console.log('success again') }
render() {
return <Grid
CustomComponent={ CustomComponent }
ActiveComponent={ ActiveComponent }
activeFunctions={ {activeFunction} }
gridItemFunctions={ { gridItemSpecificFunction:this.gridItemSpecificFunction } }
/>
}
}
根据传递的数据呈现自定义活动和网格项目的网格
class Grid extends Component {
render() {
const {CustomComponent} = this.props
return (
<GridWrapper>
{ this.props.dynamicData.map( data => (
<GridItemWrapper>
<CustomComponent { ...data } functions={ this.props.gridItemFunctions } />
</GridItemWrapper>
) )
{ active && < ActiveComponent { ...activeData }
functions={ this.props.activeFunctions }/> }
</GridWrapper>
}
)
}
}
使用通过网格项传递的函数的自定义组件示例
class CustomComponent extends Component {
render() {
const {gridItemSpecificFunction} = this.props.functions
return (
<div onClick={ gridItemSpecificFunction }>
{ this.props.text }
<div>
}
)
}
}
你真的做得很好,当然还有另一种方法可以做到这一点,可能更好只是因为更容易修改,所以你可能应该使用 Context hook 来完成这个,所以很棒的包基于它们在 Context API Hook,所以一个很好的方法就是这个
import React, { useContext, createContext, useMemo } from 'react';
const FunctionalityContext = createContext({}); // just leave it as empty state
// create a hook that return the context function
const useGridFunctions = () => {
const functions = useContext(FunctionalityContext);
return functions;
};
const CustomComponent = () => {
const functions = useGridFunctions();
return (
<div>
<button onClick={functions.gridItemSpecificFunction}>I am a custom component</button>
</div>
);
}
const ActiveComponent = () => {
const functions = useGridFunctions();
return (
<div>
<button onClick={functions.activeFunction}>I am a active component</button>
</div>
);
}
const ParentGrid = ({ functions }) => {
const functions = useMemo(() => functions, [functions]);
// the pass functions object to our context provider to get accesso through dom tree
return (
<FunctionalityContext.Provider value={functions}>
<Grid
CustomComponent={CustomComponent}
ActiveComponent={ActiveComponent}
/>
</FunctionalityContext.Provider>
);
}
如您所见,您仍然保持代码几乎相同,但您添加了一个额外的层来存储组件将使用的功能,因此 Context Api 将帮助您实现这一目标随心所欲