React分类图片画廊祖孙组件传type参数失效致图片无法渲染
React图片画廊参数传递失效导致图片不渲染问题修复
核心问题点
图片URL拼接错误本质是3个传参/作用域问题叠加导致的:
- 父组件
ImagesList调用useFetch时,没有把拿到的type(图片地址前缀参数)传给自定义Hook useFetch内部的fetchData函数重复声明了view形参,调用时又没传值,导致函数内部拿到的view永远是undefined,直接覆盖了Hook外层接收到的参数useFetch的useEffect依赖数组漏了图片前缀参数,参数变化时不会重新生成正确的图片地址
另外代码里还有3个会直接导致页面报错的问题:
ImagesList组件里渲染了未定义的变量eleven- JSX的map循环里写了位置错误的行注释
// </div>,会被解析为正常文本触发渲染错误 - 顶层分类组件(比如Books)的函数形参写法不规范,React组件只会把所有props合并为第一个参数传入,写两个形参无法正确拿到传入值
- 循环渲染的列表项没加唯一
key属性,img标签没加alt属性,会触发控制台告警
修复后代码
1. 最内层自定义Hook(useFetch.js)
去掉重复形参,补全参数传递和依赖项,修正async/await和then混用的写法:
import { useState, useEffect } from "react"; export const useFetch = (address, view) => { const [data, setData] = useState([]); const [error, setError] = useState(); // 去掉fetchData重复声明的view形参,直接使用外层Hook接收到的view const fetchData = async () => { try { const res = await fetch(address); const json = await res.json(); const finalData = json.map((elem) => { const imageUrl = `${view}${elem.id}`; return { id: elem.id, title: elem.title, image: imageUrl, }; }); setError(undefined); setData(finalData); } catch (e) { console.error("请求错误: ", e); setError(e); } }; useEffect(() => { fetchData(); // 补全依赖项,address或view变化时重新执行逻辑 }, [address, view]); return { data, error }; };
注意:React 17+版本支持新的JSX转换,不需要在组件/Hook文件里显式导入React
2. 中间层列表组件(ImagesList.jsx)
调用Hook时传入type参数,删掉无效变量和错误注释,补全必要标签属性:
import { useFetch } from "./useFetch"; function ImagesList({ category, number, type }) { const address = `https://jsonplaceholder.typicode.com/albums/${number}/photos`; // 把type作为第二个参数传给useFetch,对应Hook里的view形参 const { data, error } = useFetch(address, type); return ( <div> <h1 className="header__title">{category}</h1> {error && <p>加载出错: {error.message}</p>} <main className="container"> <div className="items-list" data-style="cards"> {data.map((item) => ( <div className="items-list__item item" key={item.id}> <img className="item__img" src={item.image} alt={item.title} /> <div className="item__info"> <div className="caption"> <h6 className="item__name text--center">{item.title}</h6> <div className="item__description"> 可替换为对应分类的统一描述内容 </div> <p className="heart d-inline-block"> <button>加入收藏</button> </p> </div> </div> </div> ))} </div> </main> </div> ); } export default ImagesList;
3. 顶层分类组件(以Books为例,Albums、Movies写法完全一致,仅传入参数不同)
修正组件形参写法,保持参数传入正确即可:
import "../styles/images.css"; import "../styles/favorites.css"; import ImagesList from "./ImagesList"; // 未使用props参数时直接写空括号即可 const Books = () => { return ( <ImagesList category="Books" number="2" type="https://api.lorem.space/image/book?w=150&h=220&hash=$" /> ); } export default Books;
其余两个分类组件只需要修改传入的category、number、type三个属性值即可,不需要重复编写任何数据请求和渲染逻辑。
内容的提问来源于stack exchange,提问作者knowledge
相关产品推荐
相关产品推荐

