Я пытаюсь получить все продукты из моего API.
Код API для продуктов приведен ниже.
Код ниже работает хорошо:
const heh = () => {
products.map((p) => console.info(p.id))
}
Проблема в том, что products.map в моем const allProducts
говорит мне TypeError: products.map is not a function
.
P.S. Я проверил все типы. Я получаю массив объектов.
Полный код ниже:
const Product = ({products}) => {
const heh = () => {
products.map((p) => console.info(p.id))
}
const allProducts = products.map((p) => (
<div className = "product" key = {p.id}>
<h3>{p.name} - {p.price}</h3>
<p>{p.description}</p>
</div>)
)
return (
<div>
<button onClick = {() => heh()}>Click</button>
{allProducts}
</div>
)
}
const Test = () => {
const [products, setProducts] = React.useState([])
React.useEffect(() => {
const fetchProducts = async () => {
const result = await axios('/api/v1/products')
console.info(result.data.data)
setProducts(result.data)
}
fetchProducts()
}, [])
return (
<div>
<Product products = {products} />
</div>
)
}
ReactDOM.render(React.createElement(Test), document.getElementById('app'))
ТС:
const result = await client.query("SELECT * FROM products")
const products = new Array()
result.rows.map(p => {
let obj: any = new Object()
result.rowDescription.columns.map((el, i) => {
obj[el.name] = p[i]
})
products.push(obj)
})
response.body = {
success: true,
data: products
}
React.useState(0)
, начните с числа, вы ожидаете, что это будет массив. Что? Я имею в виду, что useEffect
делает что-то после рендеринга, ваш fetch
асинхронный, это две причины, по которым ваше значение по умолчанию имеет значение?
в своем тесте вы делаете console.info(result.data.data)
, но затем вы передаете result.data
функции setProducts
. Вы уверены, что нет вложенной переменной с именем data
, где внутренняя data
— это массив продуктов.
продукты инициализируются числом (0), тогда вы назначаете массив, поэтому он должен быть const [products, setProducts] = React.useState([])
почему бы вам вместо этого не попробовать это:
return (
<div>
<button onClick = {() => heh()}>Click</button>
{products.map((p) => (
return (<div className = "product" key = {p.id}>
<h3>{p.name} - {p.price}</h3>
<p>{p.description}</p>
</div>))}
</div>
)
та же проблема. Я знал об этом, и это был мой первый вариант :(
как предложено другими, сделайте это const [products, setProducts] = React.useState([])
вы делаете console.info result.data.data
, но храните внутри продукты result.data
, может ли это вызвать проблему?
Ваше начальное состояние для products
— 0
. Это означает, что когда вы передадите его в Product
в первый раз, это будет число, а не массив. У чисел нет функции map
, поэтому вы получите сообщение об ошибке.
Если products
будет массивом, используйте []
в качестве его начального состояния:
const [products, setProducts] = React.useState([])
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^
...или значение флага, например null
, которое вы проверяете перед попыткой использовать map
.
Примечание: вы неправильно используете map
. Если вы не возвращаете значение из обратного вызова map
и не используете новый массив, который создает map
, вам не следует использовать map
. Используйте forEach
или простой цикл.
Ага. Ты был прав. Что-то происходит с моим приложением по некоторым причинам. Спасибо.
Когда ваша функция heh
выполняется, список продуктов загружается и представляет собой массив.
Вы получили ошибку в строке const allProducts = ...
, потому что вы установили значение продуктов по умолчанию в виде числа. В этой строке
const [products, setProducts] = React.useState(0)
Замените пустым массивом по умолчанию, чтобы решить вашу проблему:
const [products, setProducts] = React.useState([])
Вы получаете ошибку, потому что вы инициализируете состояние свойства продуктов значением 0, которое не является итерируемым объектом. Инициализируйте его с помощью useState([]).
Когда вы вводили заголовок вопроса, вы должны были сразу определить свою проблему -
React
.map
не является функцией для массива объектов
Вы думаете, что у вас есть массив объектов. Но если у вас нет .map
для его вызова, то у вас нет массива. На самом деле, это так просто.
нет!!! кто научил тебя так писать код? вы используете .map
неправильно двумя способами: 1) как .forEach
и 2) как .reduce
. Более правильное использование response.body = { success: true, products: results.rows.map(row => result.rowDescription.columns.reduce((r, col, i) => Object.assign(r, { [col.name]: row[i] }), {}))
Вы уверены, что проверили типы в нужное время? Я бы предложил либо установить точку останова отладчика на строке
const allProducts = products.map((p) => (
и проверить значениеproducts
, когда программа останавливается там, либо добавитьconsole.info("products:", products)
непосредственно перед этой строкой.