我想构建类似于此图像中的侧边栏组件:sidebar-components
而不是通过道具将带有文本值的子组件作为对象传递,我想为列表中每个元素中的每个键值对创建一个单独的组件。例如:如果列表中有3个元素,则列表中每个元素应有3个组成部分。
到目前为止是我的代码:
import React from 'react'
function SidebarComponents({ name, title, selected, onSelect }) {
const style = {
cursor: 'pointer'
}
return (
<div
name={name}
title={title}
style={style}
onClick={() => {
if (onSelect) onSelect(name)
}}
>
</div>
)
}
export default SidebarComponents
import React, { useEffect, useState } from 'react'
import SidebarComponents from '../../components/Sidebar1/Sidebar'
function Sidebar({ onChange }) {
const [selectedComponent, setSelectedComponent] = useState({
componentsName: [
{ name: 'Overview', title: 'Overview' },
{ name: 'SPO2', title: 'SPO2' }
]
})
return (
<div>
{selectedComponent.componentsName.map(componentsName => {
return (
<SidebarComponents
name={componentsName.name}
title={componentsName.title}
/>
)
})}
</div>
)
}
export default Sidebar
我如何更改代码以映射列表的子组件,而不是表示它们的对象的列表?
我希望我的问题清楚。
[下面是使用render props和hooks的更深入的解决方案-我建议阅读链接文档,因为钩子和渲染道具很棒。请注意,钩子仅从React 16.8开始可用。
简单来说,在下面的示例中,边栏使用父组件render
提供的App
道具进行渲染。在render
的SidebarComponent
道具中,该函数表示要渲染Title
和Name
组件。 name
函数的map
用作onClick
处理程序的参数,并且无需将所选的组件对象传递到侧边栏即可将selected
设置为true
或false
。 >
[如果要提供侧边栏可以渲染的组件的主列表,然后将这些集合中的哪一个传递给道具,则必须过滤componentsName
数组,以便仅道具中提供的那些对于SidebarComponent
。
import React from 'react'
import ReactDOM from 'react-dom'
/**
* Title component
* @param {string=''} props.title
*/
const Title = ({ title = '' }) => <h2>{title}</h2>
/**
* Name component
* @param {string=''} props.name
*/
const Name = ({ name = '' }) => <div>{name}</div>
/**
* SidebarComponent styles
*/
const style = {
cursor: 'pointer'
}
/**
* SidebarComponent classes
*/
const classes = {
selected: {
backgroundColor: '#00ff00'
}
}
/**
* @func SidebarComponent
* @param {string=''} name
* @param {function} onClick
* @param {boolean=false} selected
* @param {string=''} title
* @returns {React.Node} react component that returns a div
* containing two other components: Title and Name
*/
const SidebarComponent = ({
name = '',
onClick,
selected = false,
title = ''
}) => (
<div
onClick={onClick && onClick}
style={{
...style,
...(selected ? classes.selected : {})
}}
>
<Title title={title} />
<Name name={name} />
</div>
)
/**
* @func Sidebar
* @param {Array[{title: string, name: string}]} componentsName an
* arry of components to render inside the sidebar, as SidebarComponents
* @param {function} renderProp render function that dictates
* what to render inside of the sidebar
* @returns {Node} returns the calling of the renderProp function
*/
const Sidebar = ({ componentsName, render }) => {
const [selectedComponentName, setSelectedComponentName] = React.useState(null)
const handleClick = name => setSelectedComponentName(name)
return (
<div id="sidebar">
{render({
selectedComponentName,
handleClick
})}
</div>
)
}
/**
* An array of the components to render inside the Sidebar
*/
const componentsName = [
{ name: 'Overview', title: 'Overview' },
{ name: 'SPO2', title: 'SPO2' }
]
/**
* @func App
* @returns {React.Node} a react component that renders the sidebar
*/
const App = () => (
<Sidebar
render={({ selectedComponentName, handleClick }) =>
componentsName.map(({ name, ...props }, index) => (
<SidebarComponent
selected={name === selectedComponentName}
key={`sidebar-component-${index}`}
onClick={() => handleClick(name)}
{...{
name,
...props
}}
/>
))
}
/>
)
ReactDOM.render(<App />, document.getElementById('container'))
演示
在此演示中,您可以单击任一菜单项,然后看到所选的项目将背景色更改为绿色。