【发布时间】:2021-12-22 07:11:56
【问题描述】:
首先,感谢您的支持。
作为 ReactJS 世界的新手,我正在尝试完成一个产品商店的概念示例,其中包含一些过滤器作为复选框。这个想法是您选择一个过滤器,您会显示具有所选属性的产品。
一切正常,除了当您刷新页面时,您会看到过滤器列和应该出现产品的空白列,即使 console.log(state) 会返回正确的对象数组。
当您单击复选框(过滤器)时,它会正确呈现并显示产品。
GITHUB LINK 代表完整的code。
这里是刷新时不显示的组件 CardProduct。
import React, { useContext, useEffect } from 'react'
import { AppContext } from '../../App'
import { Hearty } from '../Hearty'
import Star from '../Star'
import boiler from '../../images/boiler.png'
import Confronta from '../Confronta'
const CardProduct = ({ count, setCount }) => {
const [state, dispatch] = useContext(AppContext)
console.log('State in CardProduct:', state)
function returnCardProduct () {
return (
state.map((item, i) => {
const { brand, descrizione, prezzo, note, stelle } = item
return (
<div className="row">
<div className="colcard">
<div key={ i } className="card"
style={ { width: 'auto', height: 'auto' } }>
<Hearty/>
<img className="card-img-top" src={ boiler } alt="boiler"/>
<div className="card-body">
<p className="card-title"> { brand.toUpperCase() }</p>
<h6 className="card-text">{ descrizione }</h6>
<Star stelle={ stelle }/>
<h4> { prezzo } </h4>
<h5> { note } </h5>
<Confronta count={ count } setCount={ setCount }/>
</div>
</div>
</div>
</div>
)
}))
}
return (
<div className="container">
{ returnCardProduct() }
</div>
)
}
export default CardProduct
这里是过滤器组件
import { useContext, useEffect, useState } from 'react'
import { AppContext } from '../App'
const Filters = () => {
const [stock, setStock] = useState([])
const [state,dispatch] = useContext(AppContext)
function fetchInitialStock () {
async function fetchStock () {
let result1 = await fetch('http://localhost:9000/stock').
then(result1 => result1.json()).
then(data => setStock(data))
}
fetchStock()
return stock
}
useEffect (()=>fetchInitialStock(),[])
console.log( 'initStock' ,stock)
return (
<>
<div className="container">
<div className="row">
<div className="categories">
<p>CATEGORIE</p>
<h6>Riscaldamento</h6>
<h6>Casa e acqua</h6>
<h6>Casa</h6>
<h6>Acqua</h6>
</div>
<div className="scegli">
<p>SCEGLI PER</p>
<h6><span><input type="checkbox"
name="DISPONIBILI"
onChange={(e)=> {
e.target.checked ? dispatch({ type: 'DISPONIBILI' }) : dispatch({ type:'PREV' })
} }/>
</span> Disponibili ({stock.map((item) => item.disponibili )}) </h6>
<h6><span><input type="checkbox"
name="PROMO"
onChange={(e)=> e.target.checked ? dispatch({ type: 'PROMO' }) : dispatch({ type: 'PREV' }) }
/> </span>In Promozione ({ stock.map((item) => item.inSconto) }) </h6><br/>
</div>
<div className="marche">
<p>MARCHE</p>
<h6><span><input type="checkbox" name="ariston" onChange={(e)=>{
e.target.checked
? dispatch({ type: 'ARISTON' })
: dispatch({ type: 'PREV' })
}}
/> </span> Ariston ({stock.map((item)=>item.hasOwnProperty('brand')? item.brand.ariston: null)})</h6>
<h6><span><input type="checkbox" name="baxi" onChange={(e)=>{
e.target.checked
? dispatch({ type: 'BAXI' })
: dispatch({ type: 'PREV' })
}}/> </span>Baxi ({stock.map((item)=>item.hasOwnProperty('brand')? item.brand.baxi : null)})</h6><br/>
</div>
<div className="tipologia">
<p>TIPOLOGIA</p>
<h6><span><input type="checkbox" name="condensazione" onChange={(e)=>{
e.target.checked
? dispatch({ type: 'CONDENSAZIONE' })
: dispatch({ type: 'PREV' })
}}/> </span> A Condensazione ({stock.map((item)=>item.hasOwnProperty('tipologia')? item.tipologia.condensazione: null)}) </h6>
<h6><span><input type="checkbox" name="cameraAperta" onChange={(e)=>{
e.target.checked
? dispatch({ type: 'APERTA' })
: dispatch({ type: 'PREV' })
}}/> </span>Camera Aperta ({ stock.map((item)=>item.hasOwnProperty('tipologia')? item.tipologia.cameraAperta: null) }) </h6>
<h6><span><input type="checkbox" name="cameraStagna" onChange={(e)=>{
e.target.checked
? dispatch({ type: 'STAGNA' })
: dispatch({ type: 'PREV' })
}}/> </span>Camera Stagna ({ stock.map((item)=>item.hasOwnProperty('tipologia')? item.tipologia.cameraStagna: null) })</h6><br/>
</div>
</div>
</div>
</>
)
}
export default Filters
..最后是 App()
import CardProduct from './components/CardProduct'
import { createContext, useReducer, useState, useEffect } from 'react'
import Filters from './components/Filters'
import Footer from './components/Footer/Footer'
export const AppContext = createContext()
function App () {
const [count, setCount] = useState(0)
function setInit (data, array) {
data.map((item) => array.push(item))
return array
}
/*Function for setting BOILERS from fetch*/
function fetchInitialBoiler () {
let initB = []
async function fetchBoilers () {
let response = await fetch('http://localhost:9000/boilers').
then(response => response.json()).
then(data => setInit(data, initB))
}
fetchBoilers()
return initB
}
const initBoilers = fetchInitialBoiler()
const [prev, setPrev] = useState([])
const [state, dispatch] = useReducer(reducer, initBoilers)
/* Define the reducer function*/
function reducer (state, action) {
let current
switch (action.type) {
case 'DISPONIBILI':
current = []
current = state.filter((item) => item.disponibile ? item : null)
setPrev(current)
return current
case 'PROMO':
current = []
current = state.filter((item) => item.inSconto ? item : null)
setPrev(current)
return current
case 'ARISTON':
current = []
current = state.filter(
(item) => ((item.hasOwnProperty('brand')) &&
(item.brand === 'Ariston'))
? item
: null)
setPrev(current)
return current
case 'BAXI':
current = []
current = state.filter(
(item) => (item.hasOwnProperty('brand')) && (item.brand === 'Baxi')
? item
: null)
setPrev(current)
return current
case 'CONDENSAZIONE':
current = []
current = state.filter((item) => (item.hasOwnProperty('tipologia')) &&
(item.tipologia === 'condensazione')
? item
: null)
setPrev(current)
return current
case 'APERTA':
current = []
current = state.filter((item) => (item.hasOwnProperty('tipologia')) &&
(item.tipologia === 'camera-aperta')
? item
: null)
setPrev(current)
return current
case 'STAGNA':
current = []
current = state.filter((item) => (item.hasOwnProperty('tipologia')) &&
(item.tipologia === 'camera-stagna')
? item
: null)
setPrev(current)
return current
case 'PREV':
current = []
/*console.log('PREV', prev)*/
return prev
default:
return state
}
}
return (
<>
<AppContext.Provider value={ [state, dispatch] }>
<main>
<div className="container">
<div className="container">
<>
<div className="col align-self-start">
<Filters/>
</div>
<div className="col-9">
<CardProduct count={ count } setCount={ setCount }/>
</div>
</>
</div>
</div>
<>
<div>
<Footer className="footer" count={ count }/>
</div>
</>
</main>
</AppContext.Provider>
</>
)
}
export default App
--- 谢谢---
【问题讨论】:
-
更新 |按照 sid 的建议(谢谢),我在组件内部使用(但我也在 App() 中尝试过)useState 挂钩从 API 中获取(),并在组件 CardProduct 中的 useEffect 挂钩中设置状态。它在第一次渲染,但我找不到将状态 (const [init,setInit]) 传递给 useReducer 钩子的方法。这似乎是错误的,因为 useReducer 做同样的事情。尝试仅在组件内部使用 useReducer,但它不从 fetch() 获取 initialState(在 useEffect 内部或外部)。我还尝试了没有结果的延迟初始化。
-
主要问题是我无法从组件内部的useReducer钩子中的fetch()中获取initialState。
标签: javascript reactjs react-redux react-hooks jsx