我正在尝试制作一棵树并使用上下文API,以便树的所有节点都可以调用父函数。
这是我的树的开始
<Filter>
{dataSource.map((x, i) => {
return <DataTree
key={i}
name={x.name}
type={x.type}
children={x.children}
/>
})}
</Filter>
这是我的树节点
function DataTree(props) {
const [isOpen, setIsOpen] = useState(false)
return (
<div className="mt-3">
<div className="row">
{props.children &&
<button className="btn-primary mr-2" onClick={() => setIsOpen(!isOpen)}>+</button>
}
<h5 onClick={() => props.setFilter(props.name, props.type)}>{props.name}</h5>
</div>
<h1>{JSON.stringify(props.filters)}</h1>
<div className="pl-5">
<Filter>
{isOpen && props.children && props.children.map((x, i) => {
return <DataTree
key={i}
name={x.name}
type={x.type}
children={x.children}
/>
})}
</Filter>
</div>
</div>
)
}
export default withFilter(DataTree)
这是我的上下文 API 的 HOC
const FilterContex = React.createContext()
export function Filter(props) {
const [filters, setFilters] = useState({})
const addToFilter = (value, name) => {
setFilters({ ...filters, [name]: value })
}
return (
<FilterContex.Provider value={{ filters, setFilter: addToFilter }}>
{props.children}
</FilterContex.Provider>
)
}
export function withFilter(Component) {
return function FilterComponent(props) {
return (
<FilterContex.Consumer>
{context => <Component {...props} {...context} />}
</FilterContex.Consumer>
)
}
}
问题是在我的DataTree
中,我正在渲染的DataTree
不是具有withFilter
的,因此只有树的第一个节点具有上下文 API。
如何自行渲染包含withFilter
的DataTree
?另外,我不确定我是否使上下文API正常工作。
由于您使用的是钩子,因此最好将钩子作为模式而不是 HOC。因此,您的解决方案将包括使用useContext
钩子来访问组件中的上下文
数据树
function DataTree(props) {
const [isOpen, setIsOpen] = useState(false)
const {filters, setFilter} = useContext(FilterContex);
return (
<div className="mt-3">
<div className="row">
{props.children &&
<button className="btn-primary mr-2" onClick={() => setIsOpen(!isOpen)}>+</button>
}
<h5 onClick={() => setFilter(props.name, props.type)}>{props.name}</h5>
</div>
<h1>{JSON.stringify(filters)}</h1>
<div className="pl-5">
<Filter>
{isOpen && props.children && props.children.map((x, i) => {
return <DataTree
key={i}
name={x.name}
type={x.type}
children={x.children}
/>
})}
</Filter>
</div>
</div>
)
}
export default DataTree;
过滤器接口
export const FilterContex = React.createContext()
export function Filter(props) {
const [filters, setFilters] = useState({})
const addToFilter = (value, name) => {
setFilters({ ...filters, [name]: value })
}
return (
<FilterContex.Provider value={{ filters, setFilter: addToFilter }}>
{props.children}
</FilterContex.Provider>
)
}
如果您想知道如何使用 HOC 实现相同的效果,则需要创建一个新的连接 DataTree 组件并将其用于嵌套渲染
function DataTree(props) {
const [isOpen, setIsOpen] = useState(false)
return (
<div className="mt-3">
<div className="row">
{props.children &&
<button className="btn-primary mr-2" onClick={() => setIsOpen(!isOpen)}>+</button>
}
<h5 onClick={() => props.setFilter(props.name, props.type)}>{props.name}</h5>
</div>
<h1>{JSON.stringify(props.filters)}</h1>
<div className="pl-5">
<Filter>
{isOpen && props.children && props.children.map((x, i) => {
return <DataTreeWithFilter
key={i}
name={x.name}
type={x.type}
children={x.children}
/>
})}
</Filter>
</div>
</div>
)
}
const DataTreeWithFilter = withFilter(DataTree);
export default DataTreeWithFilter;