简体   繁体   English

如何使用条件渲染编写干净、可读的 ReactJS 组件?

[英]How to write clean, readable ReactJS Components with conditional renders?

The result is not showing in my window.结果未显示在我的 window 中。 I have created a global object for testing:我创建了一个全局 object 用于测试:

const obj = {
  onam: [
    {
      name: "name3",
      image: "https://resize.hswstatic.com/w_828/gif/kelp-biofuel.jpg"
    },
    {
      name: "name2",
      image: "https://resize.hswstatic.com/w_828/gif/kelp-biofuel.jpg"
    }
  ],
  christmas: [
    {
      name: "name1",
      image: "https://resize.hswstatic.com/w_828/gif/kelp-biofuel.jpg"
    },
    {
      name: "name0",
      image: "https://resize.hswstatic.com/w_828/gif/kelp-biofuel.jpg"
    }
  ]
}

Below is the function I am calling inside render.下面是我在渲染中调用的 function。

const grid = (props) => {
  if (props == "All") {
    const keys = Object.keys(obj);
    // looping through keys
    keys.forEach((key, index) => { 
      // looping through array in keys
      for(let j = 0; j < Object.keys(obj).length; j++) {
        return (
          <div>
            <a><img src={obj[key][j].image}>{obj[key][j].name}</img></a>
          </div>
        )
      }
    });   
  }
}

I know there is some error in the above function but I cant sort it out.我知道上面的 function 有一些错误,但我无法解决。 I am calling {grid("All")} inside render.我在渲染中调用{grid("All")} My aim is to display a div containing a div with all images with a tag.我的目标是显示一个 div,其中包含一个带有标签的所有图像的 div。 I would like to learn a clean way of conditionally rendering my components.我想学习一种有条件地渲染组件的干净方法。

There are several concerns here Ashwin. Ashwin 有几个问题。

  • Your component name should begin with uppercase.您的组件名称应以大写字母开头。
  • Use an array instead of object obj .使用数组而不是 object obj Its easier to work with arrays and loop through them than it is to loop objects.使用 arrays 并循环它们比循环对象更容易。
  • Don't wrap the entire component within an if statement.不要将整个组件包装在 if 语句中。 Its bad practice.它的坏习惯。
  • props == "All" is just wrong. props == "All"是错误的。 props is an object not a string. props 是 object 不是字符串。 This is the main reason nothing is rendering.这是没有渲染的主要原因。 That if statement will always return false.该 if 语句将始终返回 false。
  • <img> doesn't take children so don't pass {obj[key][j].name} into the img tag. <img>不带孩子,所以不要将{obj[key][j].name}传递给 img 标签。 Move that bit after the closing img tag into the <a> tag.将结束 img 标记之后的那个位移动到<a>标记中。

I'm rewriting your component with some comments to help you learn, but there are several other ways to achieve the same result, perhaps with a better approach.我正在重写您的组件并添加一些注释以帮助您学习,但是还有其他几种方法可以达到相同的结果,也许是更好的方法。 This works for me and I find it's more readable and easier to understand.这对我有用,我发现它更具可读性和更容易理解。

import React from "react"

/* An array of objects is always easier to work than objects with 
multiple arrays as values. You might end up duplicating a few keys like
"festival" in this example, but it will make your life easier.
 */

const arr = [
    {
      festival: "oman",
      name: "name3",
      image: "https://resize.hswstatic.com/w_828/gif/kelp-biofuel.jpg",
    },
    {
      festival: "oman",
      name: "name2",
      image: "https://resize.hswstatic.com/w_828/gif/kelp-biofuel.jpg",
    },
    {
      festival: "christmas",
      name: "name1",
      image: "https://resize.hswstatic.com/w_828/gif/kelp-biofuel.jpg",
    },
    {
      festival: "christmas",
      name: "name0",
      image: "https://resize.hswstatic.com/w_828/gif/kelp-biofuel.jpg",
    },
]

/* 
Always make sure your components are uppercase

De-structure your props with { propName1, propName2 }
because that way you or anybody else looking at your
component immediately can recognize what props are being
passed.
*/
const Grid = ({ whatToRender }) => {
  /*  
  Create a custom render function inside your component if
  you need to render conditionally. Its easier to work with
  debug and maintain. 
  */
  const renderGrid = () => {
    if (whatToRender === "all") { // use === over == because that will check for type equality as well.
      return arr.map((item) => ( // () is equivalent to return () when looping.
        /* Always pass a unique key if you are creating lists or lopping */
        <div key={item.image}> 
          <a>
            <img src={item.image} alt={item.name} />
            {item.name}
          </a>
        </div>
      ))
    }
    if (whatToRender === "onam") {
      return arr.map((item) => {
        if (item.festival === "onam") {
          return (
            <div key={item.image}>
              <a>
                <img src={item.image} alt={item.name} />
                {item.name}
              </a>
            </div>
          )
        }
      })
    }
    if (whatToRender === "christmas") {
      return arr.map((item) => {
        if (item.festival === "christmas") {
          return (
            <div key={item.image}>
              <a> {/* Image tags don't take children they are self-closing */}
                <img src={item.image} alt={item.name} />
                {item.name}
              </a>
            </div>
          )
        }
      })
    } // Return an empty div if none of the cases pass. So, you return valid JSX
    return <div></div>
  }
  return renderGrid() // Finally return your custom render function
}

export default Grid

EDIT编辑

On visiting this question again, I realized that there was a better way to write it.再次访问这个问题时,我意识到有更好的方法来编写它。 A much shorter version.一个更短的版本。 It uses the same arr defined in the above code sample.它使用上述代码示例中定义的相同 arr。

const Grid = ({ whatToRender }) => {
  const renderGrid = () => {
    return arr.map((item) => {
      if (item.festival === whatToRender || whatToRender === "all") {
        return (
          <div key={item.image}>
            <a>
              <img src={item.image} alt={item.name} />
              {item.name}
            </a>
          </div>
        )
      }
    })
  }
  return renderGrid()
}

export default Grid

Which one to use?使用哪一个? The second version not only because it's much shorter, but also because its reusable.第二个版本不仅因为它更短,而且因为它可以重复使用。 If in the future you add another festival to arr say Easter, you just need changes in the array and the prop value you are passing.如果将来您在arr中添加另一个节日,比如说复活节,您只需要更改数组和您传递的道具值。 The component will require no changes.该组件将不需要更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM