在React中向组件推送元素列表

问题描述 投票:0回答:1

我想建立一个类似于这张图片中的侧栏组件。我想为列表中每个元素中的每个键值对创建一个单独的组件,而不是将子组件作为带有文本值的对象通过道具传递。例如:如果列表有3个元素,那么列表中的每个元素应该有3个组件。

这是我目前的代码。

sidebarcomponents.js:

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

sidebar.js:


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

我如何改变我的代码,以映射一个列表的子组件,而不是一个代表它们的对象列表?

我希望我的问题是清楚的。

reactjs components
1个回答
0
投票

@shubham-khatri的回答是正确的:你需要在组件中包含文本。

下面是一个更深入的解决方案,使用 渲染道具钩子 -- 我建议阅读链接的文档,因为钩子和渲染道具非常棒。请注意,钩子只有在React 16.8版本中才有。

简单来说,在下面的例子中,侧边栏的渲染使用了 render 由父组件提供的道具。App. 在 render 烘托 SidebarComponent,函数说要渲染一个 Title 和a Name 组成部分。该 name 来自 map 函数的参数。onClick 处理器,并设置 selectedtruefalse而不需要将选定的组件对象传递给侧边栏。

如果你想提供一个侧边栏可以渲染的组件的主列表,然后将其中的哪些组件传递到道具中,那么你将不得不过滤 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。

在这个演示中,你可以点击任何一个菜单项,并看到所选项目的背景色变为绿色。


0
投票

你需要在组件内部的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。

© www.soinside.com 2019 - 2024. All rights reserved.