如何使用条件渲染编写干净、可读的 ReactJS 组件?
How to write clean, readable ReactJS Components with conditional renders?
我的 window 中没有显示结果。我创建了一个用于测试的全局对象:
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"
}
]
}
下面是我在 render 中调用的函数。
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>
)
}
});
}
}
我知道上面的函数有一些错误,但我无法解决。我在渲染中调用 {grid("All")}
。我的目标是显示一个 div 包含一个 div 以及所有带有标签的图像。我想学习一种干净的方法来有条件地渲染我的组件。
Ashwin 这里有几个问题。
- 您的组件名称应以大写字母开头。
- 使用数组代替 object
obj
。使用数组并循环遍历它们比循环 objects. 更容易
- 不要将整个组件包含在 if 语句中。这是不好的做法。
props == "All"
是错误的。道具是 object 而不是字符串。这是没有渲染的主要原因。该 if 语句将始终 return false。
<img>
不接受 children 所以不要将 {obj[key][j].name}
传递到 img 标签中。将结束 img 标签后的那个位移动到 <a>
标签中。
我正在用一些注释重写您的组件以帮助您学习,但还有其他几种方法可以达到相同的结果,也许还有更好的方法。这对我有用,我发现它更具可读性和更容易理解。
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
编辑
再次访问这个问题,我意识到有更好的写法。一个更短的版本。它使用上面代码示例中定义的相同 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
使用哪一个?第二个版本不仅因为它更短,而且因为它可以重复使用。如果将来你向 arr
添加另一个节日,比如复活节,你只需要更改数组和传递的道具值。该组件不需要更改。
我的 window 中没有显示结果。我创建了一个用于测试的全局对象:
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"
}
]
}
下面是我在 render 中调用的函数。
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>
)
}
});
}
}
我知道上面的函数有一些错误,但我无法解决。我在渲染中调用 {grid("All")}
。我的目标是显示一个 div 包含一个 div 以及所有带有标签的图像。我想学习一种干净的方法来有条件地渲染我的组件。
Ashwin 这里有几个问题。
- 您的组件名称应以大写字母开头。
- 使用数组代替 object
obj
。使用数组并循环遍历它们比循环 objects. 更容易
- 不要将整个组件包含在 if 语句中。这是不好的做法。
props == "All"
是错误的。道具是 object 而不是字符串。这是没有渲染的主要原因。该 if 语句将始终 return false。<img>
不接受 children 所以不要将{obj[key][j].name}
传递到 img 标签中。将结束 img 标签后的那个位移动到<a>
标签中。
我正在用一些注释重写您的组件以帮助您学习,但还有其他几种方法可以达到相同的结果,也许还有更好的方法。这对我有用,我发现它更具可读性和更容易理解。
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
编辑
再次访问这个问题,我意识到有更好的写法。一个更短的版本。它使用上面代码示例中定义的相同 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
使用哪一个?第二个版本不仅因为它更短,而且因为它可以重复使用。如果将来你向 arr
添加另一个节日,比如复活节,你只需要更改数组和传递的道具值。该组件不需要更改。