TypeError: categories.map не является функцией в ReactJs
Как исправить TypeError: categories.map не является функцией
'''
This is App.js:
export default function Header() {
const [categories, setCategories] = useState([]);
useEffect(() => {
const loadCategories = async () => {
let res = await API.get(endpoints['categories'])
setCategories(res.data)
}
loadCategories()
}, []);
return (
<Navbar bg="light" expand="lg">
<Container>
<Navbar.Brand href="#home">ECoursesAPP</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link className="nav-link" to="/">Trang chủ</Link>
{categories.map(c => <Link className="nav-link" to="#link">{c.name}</Link>)}
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
)
}
''' Это API.js: ''' import axios from "axios"; export let endpoints = { "categories": "/categories/" } export default axios.create({ baseURL: "http://localhost:8000" }) '''
Вы всегда должны иметь проверку на нуль перед .map, чтобы избежать ошибок во время выполнения
{(categories || []).map(c => <Link className="nav-link" to="#link">{c.name}</Link>)}
При первом рендере ваш массив categories
является пустым массивом. Поэтому вы делаете что-то вроде этого:
[].map(item => <p>{item.name}</p>)
когда в массиве нет элемента, использование точечной нотации для получения значения элемента вызовет проблему.
Для вас есть два варианта:
- добавить значение по умолчанию на этапе инициализации на
setState
, например:
const [categories, setCategories] = useState([
{id: 0, name: "" , ...}
]);
- дождитесь ответа API, прежде чем выводить
categories
:
{
categories.length > 0 && categories.map(
// rest of the codes ...
)
}
Update
есть еще одна проблема с вашим api.js
В объектах Javascript нет необходимости заключать key
в кавычки. поэтому удалите его из categories
:
let endpoints = {
categories : "/categories/"
}
Возможно, ваша конечная точка api не возвращает массив, поэтому вы можете исправить это или использовать категории?.map
Здравствуйте Согласно вашей ошибке проблема в том, что массив не показывает элемент при первом рендеринге, поэтому вы используете логику, если массив существует, то массив отображает данные, давайте я покажу вам
export default function Header() {
const [categories, setCategories] = useState([]);
useEffect(() => {
const loadCategories = async () => {
let res = await API.get(endpoints['categories'])
setCategories(res.data)
}
loadCategories()
}, []);
return (
<Navbar bg="light" expand="lg">
<Container>
<Navbar.Brand href="#home">ECoursesAPP</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link className="nav-link" to="/">Trang chủ</Link>
{categories && categories.map(c => <Link className="nav-link" to="#link">{c.name}</Link>)}
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
)
}