我正在尝试制作一棵树并使用上下文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。 / p>
如何在自身内部渲染DataTree
的{{1}}?
另外,我不确定是否要使上下文API正常工作。
答案 0 :(得分:2)
由于使用的是钩子,因此最好将钩子作为一种模式而不是HOC。因此,您的解决方案将包括使用useContext
钩子来访问组件中的上下文
DataTree
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;
过滤器API
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;