制作树时无法使用上下文 API
Can't Use Context API while making a tree
我正在尝试制作一棵树并使用上下文 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)
这是上下文的 HOC API
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
挂钩访问组件中的上下文
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;
我正在尝试制作一棵树并使用上下文 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)
这是上下文的 HOC API
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
挂钩访问组件中的上下文
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;