我想建立一个类似于这张图片中的侧栏组件。我想为列表中每个元素中的每个键值对创建一个单独的组件,而不是将子组件作为带有文本值的对象通过道具传递。例如:如果列表有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
我如何改变我的代码,以映射一个列表的子组件,而不是一个代表它们的对象列表?
我希望我的问题是清楚的。
@shubham-khatri的回答是正确的:你需要在组件中包含文本。
下面是一个更深入的解决方案,使用 渲染道具 和 钩子 -- 我建议阅读链接的文档,因为钩子和渲染道具非常棒。请注意,钩子只有在React 16.8版本中才有。
简单来说,在下面的例子中,侧边栏的渲染使用了 render
由父组件提供的道具。App
. 在 render
烘托 SidebarComponent
,函数说要渲染一个 Title
和a 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'))
https:/codesandbox.iosreact-playground-wnxer?file=index.js。
在这个演示中,你可以点击任何一个菜单项,并看到所选项目的背景色变为绿色。
你需要在组件内部的DIV中渲染名称,而不是像DIV那样把它作为一个道具传递给DIV
function SidebarComponents({name,title,selected,onSelect}) {
const style={
cursor: "pointer"
};
return (
<div
title = {title}
style={style}
onClick={() => {if (onSelect) onSelect(name)}}
>
{name}
</div>
)
}
当你在贴图后渲染时,也要将onSelect和选定的道具传递给SidebarComponents。