Raj*_*han 5 javascript typescript reactjs react-children
我想制作一个具有独特模式的高度可重用的反应组件。假设这个联系人列表是由另一个团队制作的;我们无法更改组件,它遵循如下所示的结构。
<Component>
<Child1 key="child1" />
<Child2 key="child2" />
<Child3 key="child3" />
</Component>
Run Code Online (Sandbox Code Playgroud)
示例联系人列表组件:
<ContactList key="contact-list">
<ContactList.Header key="contactlist-header" />
<ContactList.Body key="contactlist-body" />
<ContactList.Footer key="contactlist-footer" />
</ContactList>
Run Code Online (Sandbox Code Playgroud)
我想提供自定义联系人列表组件的选项,例如
我想公开一些与此类似的 API。
UI.ContactList.remove("contactlist-footer") // 从 ContactList 中删除并存储在变量中以供以后使用
UI.ContactList.add(<CustomContactListFooter/>)// 将 Component 添加到 ContactList 并存储在变量中以供以后使用
其中 UI 是某个命名空间/类
所以我需要一个包装组件,它允许我根据上面的 api 操作 ContactList 的子组件,假设UI.ContactList.remove("contactlist-footer")删除 API 将数据存储在这个变量中_removeRequest = ['contactlist-footer']
在渲染组件时,我不想显示此组件 <ContactList.Footer key="contactlist-footer">,我可以通过像这样的操作在 ContactList 组件中进行操作
高层次的想法:
function ContactList({children}){
const removeKey = UI.ContactList._removeRequest[0]
const newChildren = React.Children.toArray(children).filter(child => child.key !== removeKey)
return <React.Fragement>{newChildren}</React.Fragement>
}
Run Code Online (Sandbox Code Playgroud)
这是不可能的,因为我们不允许修改 ContactList 组件。
<Parent>
<ContactList/>
</Parent>
Run Code Online (Sandbox Code Playgroud)
<Component>
<Child1 key="child1" />
<Child2 key="child2" />
<Child3 key="child3" />
</Component>
Run Code Online (Sandbox Code Playgroud)
<ContactList key="contact-list">
<ContactList.Header key="contactlist-header" />
<ContactList.Body key="contactlist-body" />
<ContactList.Footer key="contactlist-footer" />
</ContactList>
Run Code Online (Sandbox Code Playgroud)
如何从父组件操作 ContactList 的子组件?任何想法都会有所帮助
好吧,我想从不要这样做开始!- 你想要的不是 React 应用程序或组件应该如何工作。你应该只通过上面的 props 和 Context 来控制你的组件。这就是 React 应该如何工作的。
你建议的 UI 类或命名空间还会在 React 之外存储应用程序的一些状态,一些常用的库(如 redux、zustand 等)也会这样做,但这很容易出错,恕我直言,这是需要避免的反应。
尽管如此,这里还是您想要的功能的工作演示(通过组件的 props 处理Parent,而不是外部类)。正如您所看到的,我没有像 React 那样渲染组件,而是直接调用函数。
我很确定这对于维护和破坏很多东西来说是很糟糕的(只要事情不像这里那么微不足道),但对于这个简短的演示来说它是有效的。
function App() {
return (
<div className="App">
{/* remove body and header */}
<Parent removeKeys={["contactlist-body", "contactlist-header"]}>
<ContactList />
</Parent>
<hr/>
{/*add a second footer at array index 3 */}
<Parent insertChildren={{3: <ContactListFooter2 />}}>
<ContactList />
</Parent>
<hr />
{/*replace the footer with a custom one */}
<Parent removeKeys={["contactlist-footer"]} insertChildren={{2: <ContactListFooter2 />}}>
<ContactList />
</Parent>
<hr/>
{/*replace the entire component*/}
<Parent replaceComponent={<ContactListFooter2 />}>
<ContactList />
</Parent>
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
function Parent({ children, removeKeys=[], insertChildren={}, replaceComponent=undefined }) {
if(replaceComponent){
return replaceComponent;
}
// this is really hacky - don't do it
const renderedChildren = children["type"]();
renderedChildren.props.children = renderedChildren.props.children.filter(child=>!removeKeys.includes(child.key));
for(let [index, component] of Object.entries(insertChildren)){
renderedChildren.props.children.splice(index, 0, component["type"]())
}
return renderedChildren;
}
function ContactList() {
return (
<React.Fragment>
<ContactListHeader key="contactlist-header" />
<ContactListBody key="contactlist-body" />
<ContactListFooter key="contactlist-footer" />
</React.Fragment>
);
}
function ContactListHeader() {
return <h2>Header</h2>;
}
function ContactListBody() {
return <section>Body Content</section>;
}
function ContactListFooter() {
return <footer>Contact List Footer</footer>;
}
function ContactListFooter2() {
return <footer>Contact List Footer2</footer>;
}Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<body>
<div id="root"></div>
</body>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1454 次 |
| 最近记录: |