Renderizado de lista de artículos con JSX
En este capítulo aprenderás a usar expresiones JSX para renderizar datos de JS en la interfaz, haciendo que la página de inicio del blog muestre una lista de tarjetas de artículos.
{} para incrustar expresiones en JSX
En JSX,las llaves {}son la puerta de entrada al mundo de JavaScript.
Cualquier expresión de JS se puede colocar entre llaves: variables, operaciones, llamadas a funciones, expresiones ternarias, etc.
Ejemplo
const blogTitle = 'Notas de frontend de EJEMPLO'
const author = 'Xiaoming'
return (
<div>
<h1>{blogTitle}</h1>
<p>Autor:{author}</p>
<p>Hora actual:{new Date().toLocaleDateString()}</p>
<p>Mensaje de bienvenida:{author ?`Hola, ${author}` : 'Bienvenido visitante'}</p>
</div>
)
}
La página mostrará:
EJEMPLO 前端笔记 作者:小明 当前时间:2024/5/15 欢迎语:你好,小明
Dentro de las llaves solo se pueden ponerexpresiones(código que produce un valor), no sentencias. Por ejemplo,
{if (condition) ...}no es válido, pero{condition ? 'A' : 'B'}es válido.
Vinculación de atributos
Los atributos HTML en JSX deben vincularse dinámicamente con llaves.
Ejemplo
const coverUrl = '/images/react-cover.png'
const linkUrl = '/post/1'
return (
<div>
{/* Atributos dinámicos: las llaves vinculan variables de JS */}
<img src={coverUrl} alt=Portada del artículo />
<a href={linkUrl}>Leer artículo completo</a>
{/* Nota: class debe escribirse como className */}
<div className="card active">Contenido de la tarjeta</div>
{/* style recibe un objeto, los nombres de propiedades en camelCase */}
<div style={{ color: '#427DB8', fontSize: '16px' }}>
Texto verde
</div>
</div>
)
}
| HTML | JSX | Explicación |
|---|---|---|
class="btn" | className="btn" | class es una palabra reservada de JS |
style="color: red" | style={{ color: 'red' }} | Recibe un objeto, nombres de propiedades en camelCase |
src="xxx.html" | src={variable} | Los valores dinámicos se escriben con llaves |
onclick="fn()" | onClick={fn} | Los nombres de eventos en camelCase, pasa la referencia de la función |
Renderizado de listas: array.map()
React no tiene, como Vue,v-fortales directivas.
En JSX, para renderizar listas, se usa directamente el método de JavaScriptarray.map()método.
Ejemplo
// Simulamos datos de artículos con un array de objetos JS
const articles = [
{
id: 1,
title: 'Guía completa para empezar con React',
summary: 'Aprende React Hooks desde cero, cubriendo conceptos clave como useState, useEffect, etc.',
date: '2024-05-10',
category: 'React',
cover: '/images/react.png'
},
{
id: 2,
title: 'Explicación detallada de la programación asíncrona en JavaScript',
summary: 'Entiende de una vez Promise, async/await, el bucle de eventos y la cola de microtareas.',
date: '2024-05-08',
category: 'JavaScript',
cover: '/images/js.png'
},
{
id: 3,
title: 'Práctica de diseño CSS Grid',
summary: 'Implementa fácilmente diseños responsivos complejos con CSS Grid.',
date: '2024-05-05',
category: 'CSS',
cover: '/images/css.png'
}
]
return (
<div className="article-list">
{/* map recorre el array y cada elemento devuelve un fragmento de JSX */}
{articles.map(article => (
<div key={article.id} className="card">
<img src={article.cover} alt={article.title} />
<div className="card-body">
<span className="category">{article.category}</span>
<h3>{article.title}</h3>
<p>{article.summary}</p>
<span className="date">{article.date}</span>
</div>
</div>
))}
</div>
)
}
La importancia del atributo key
keyEs el identificador único asignado a cada elemento de la lista, que ayuda a React a reconocer qué elementos han cambiado.
Sin key, React adopta la estrategia de 'actualización en el lugar', lo que puede causar estados incorrectos y degradar el rendimiento.
| Valor de key | Consecuencia |
|---|---|
| id único (recomendado) | Rastrea correctamente cada elemento, Diff eficiente |
| Índice del array (index) | Al insertar/eliminar puede causar que el contenido de los campos de entrada se desordene |
| No escribir key | Advertencia en consola, mal rendimiento |
Siempre agrega a la JSX devuelta por map unaúnica y establekey. No uses index como key, especialmente cuando los elementos de la lista pueden insertarse, eliminarse o reordenarse.
Renderizado condicional
React no tiene v-if, pero hay tres formas de implementar el renderizado condicional.
Ejemplo
const articles = []
const isLoading = false
return (
<div>
{/* Forma 1: expresión ternaria — adecuada para elegir entre dos opciones */}
{isLoading ? (
<p>Cargando, por favor espera...</p>
) : (
<p>¡Carga completada!</p>
)}
{/* Forma 2: cortocircuito con && — adecuado para 'mostrar si hay condición, no mostrar si no la hay' */}
{articles.length === 0 && <p>Aún no hay artículos, mantente atento.</p>}
{/* Forma 3: if/else en el nivel superior del componente — adecuado para lógica compleja con múltiples condiciones */}
{articles.length > 0 ? (
<div>
{articles.map(a => <div key={a.id}>{a.title}</div>)}
</div>
) : (
<p>No hay datos</p>
)}
</div>
)
}
Comparación de tres formas de renderizado condicional
| Forma | Sintaxis | Caso de uso |
|---|---|---|
Ternaria? : | {cond ? <A /> : <B />} | Elegir entre dos, debe devolver algo |
Cortocircuito&& | {cond && <A />} | Mostrar si existe, no mostrar si no existe |
| if previo | Guardar la JSX en una variable antes del return | Casos con ramas condicionales complejas |
&&El cortocircuito tiene una trampa: cuando la condición es el número 0, se renderiza un '0'. Se recomienda&&que el lado izquierdo sea siempre un valor booleano:{list.length > 0 && ...}en lugar de{list.length && ...}。
Manos a la obra: página de inicio completa del blog
Ejemplo
import './App.css'
function App() {
const articles = [
{
id: 1, title: 'Guía completa para empezar con React',
summary: 'Aprende React Hooks desde cero, cubriendo conceptos clave como useState, useEffect, etc.',
date: '2024-05-10', category: 'React', cover: '/images/react.png'
},
{
id: 2, title: 'Explicación detallada de la programación asíncrona en JavaScript',
summary: 'Entiende de una vez Promise, async/await, el bucle de eventos y la cola de microtareas.',
date: '2024-05-08', category: 'JavaScript', cover: '/images/js.png'
},
{
id: 3, title: 'Práctica de diseño CSS Grid',
summary: 'Implementa fácilmente diseños responsivos complejos con CSS Grid.',
date: '2024-05-05', category: 'CSS', cover: '/images/css.png'
}
]
return (
<div className="app">
<header className="navbar">
<h1 className="logo">EJEMPLO Blog</h1>
<nav>
<a href="/">Inicio</a>
<a href="#">Acerca de</a>
</nav>
</header>
<main className="container">
<h2 className="section-title">Artículos recientes</h2>
{/* Renderizado condicional: si hay artículos se muestran, si no, se muestra el estado vacío */}
{articles.length === 0 ? (
<p className="empty-tip">Aún no hay artículos, mantente atento.</p>
) : (
<div className="article-grid">
{/* Renderizado de listas: map recorre el array */}
{articles.map(article => (
<div key={article.id} className="article-card">
<img src={article.cover} alt={article.title} className="card-cover" />
<div className="card-content">
<span className="card-category">{article.category}</span>
<h3 className="card-title">{article.title}</h3>
<p className="card-summary">{article.summary}</p>
<span className="card-date">{article.date}</span>
</div>
</div>
))}
</div>
)}
</main>
<footer className="footer">
<p>© 2024 EJEMPLO Blog. Powered by React.</p>
</footer>
</div>
)
}
export default App
Ejemplo
.section-title {
font-size: 24px;
margin-bottom: 20px;
color: #333;
}
.article-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
}
.article-card {
background: #fff;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
transition: transform 0.2s, box-shadow 0.2s;
cursor: pointer;
}
.article-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0,0,0,0.12);
}
.card-cover {
width: 100%;
height: 180px;
object-fit: cover;
}
.card-content {
padding: 16px;
}
.card-category {
display: inline-block;
padding: 2px 10px;
background: #e3f2fd;
color: #1976d2;
border-radius: 12px;
font-size: 12px;
margin-bottom: 8px;
}
.card-title {
font-size: 18px;
margin-bottom: 8px;
color: #222;
}
.card-summary {
font-size: 14px;
color: #666;
line-height: 1.6;
margin-bottom: 12px;
}
.card-date {
font-size: 12px;
color: #999;
}
.empty-tip {
text-align: center;
color: #999;
padding: 60px 0;
font-size: 16px;
}
Resumen del capítulo
En este capítulo has aprendido cuatro operaciones fundamentales de JSX:{}insertar expresiones, vinculación de atributos (className / style),map()renderizado de listas + key, renderizado condicional (ternario / cortocircuito).
Con esto, la página de inicio del blog ya puede renderizar dinámicamente tarjetas de artículos a partir de datos de JS.
Otras extensiones