Я работаю с Reactjs, чтобы получить информацию из базы данных и затем отобразить ее в формате PDF. Я продолжаю сталкиваться с проблемами, и я думаю, что я сузил его до того, откуда он исходит, но не уверен, что является причиной проблемы.
На следующем рисунке вы заметите, что у меня есть повтор трех журналов консоли, которые это «список» и «провайдер».
Код основного приложения:
import Header from './components/top/header'
import List from './components/list'
import {GroceryDataProvider} from './context/DataContext'
function App() {
console.log('app')
return(
<div>
<h1>React Testing App</h1>
<GroceryDataProvider>
<Header/>
<List/>
</GroceryDataProvider>
</div>)
}
export default App;
"поставщик" console.log поступает из моего GroceryDataProvider. Это просто консольный журнал c в самом верху. Внутри один useEffect () и несколько функций. Ниже приведено описание useEffect для DataProvider:
console.log('Provider')
const [groceryList, setGroceryList] = useState([]);
const [userList, setUserList] = useState([]);
const [userGroceryList, setUserGroceryList] = useState([]);
const [userItemList, setUserItemList] = useState([]);
const [userTypeList, setUserTypeList] = useState([]);
const [listId, setListId] = useState('');
const [userId, setUserId] = useState('');
const [DataLoad, setDataLoad] = useState(false);
//const [a, setA] = useState([]);
//const [lId, setLId] = useState(0);
useEffect(()=>{
console.log('effec')
const fetch = async()=>{
let db = firebase.database().ref('groceryA/');
db.once('value',snapshot=>{
snapshot.forEach(child=>{
setGroceryList(list=>[...list,child.val()])
})
})
db = firebase.database().ref('users/');
db.once('value',snapshot=>{
setUserList(snapshot.val());
})
db = firebase.database().ref('categories')
db.once('value',snapshot=>{
setUserTypeList(snapshot.val());
})
}
fetch();
},[])
//functions are here
const GetList = () => {
console.log('GETLIST');
setUserItemList([])
let db = firebase.database().ref('groceryA/'+listId+'/items');
db.once('value',snapshot=>{
snapshot.forEach(item=>{
setUserItemList(list=>[...list,item.val()])
})
})
}
return(
<DataContext.Provider value={{groceryList,userList,userGroceryList,userItemList,listId,userId,userTypeList,DataLoad,
setGroceryList,setUserList,setListId,setUserId,setUserTypeList,
ChangeUser,GetUserList,ChangeList,GetItemList,Updater,UpdateCart,WriteItem,WriteList,GetList,Delete}}>
{props.children}
</DataContext.Provider>
)
}
Другой повторный console.log - это «список», который снова является просто c console.log в верхней части другого компонента.
import React, {useContext,useEffect,useState} from 'react';
import { PDFDownloadLink, PDFViewer, Document, Page, Text } from '@react-pdf/renderer'
import MyDocument from './pdf';
import {DataContext} from 'context/DataContext'
import Card from './ItemCard';
const List = () =>{
console.log('list')
const {listId} = useContext(DataContext);
const {userItemList} = useContext(DataContext);
// {GetItemList} = useContext(DataContext);
const {Updater} = useContext(DataContext);
const {GetList} = useContext(DataContext);
const {Delete} = useContext(DataContext);
const {UpdateCart} = useContext(DataContext);
const [items, SetItems] = useState([]);
useEffect(()=>{
console.log('list id')
GetList();
},[listId])
useEffect(()=>{
console.log(userItemList)
console.log('item list')
SetItems([]);
SetItems(userItemList)
},[userItemList])
const productChange = (itemTxt, itemId) => {
SetItems(items.map(item=>{
if(item.listItemId===itemId){
return{...item,product:itemTxt}
}
return item;
}
))
}
const quantityChange = (itemTxt, itemId) => {
SetItems(items.map(item=>{
if(item.listItemId===itemId){
return{...item,quantity:itemTxt}
}
return item;
}
))
}
const cartChange = (itemId) => {
SetItems(items.map(item=>{
if(item.listItemId===itemId){
UpdateCart({...item,cart:!item.cart},item.listItemId)
return{...item,cart:!item.cart}
//console.log(item)
}
return item;}
//console.log(item)
}
))
}
return(
<div>
<p>To Find:</p>
<ul>
{//console.log(items)
}
{items.map((item,index)=>item.cart===false?
<Card key={item.listItemId} index={index}
value={item.listItemId} cart={item.cart} item={item.product}
units={item.quantity} unitType={item.unit}
cartChange={cartChange} itemChange={productChange} quantityChange={quantityChange} change={Updater} delete={Delete}/>:null)}
</ul>
<p>Found</p>
<ul>
{items.map((item,index)=>item.cart===true?<Card key={item.listItemId} index={index}
value={item.listItemId} cart={item.cart} item={item.product}
units={item.quantity} unitType={item.unit}
cartChange={cartChange} itemChange={productChange} quantityChange={quantityChange} change={Updater} delete={Delete}/>:null)}
</ul>
</div>
)
}
export default List;
Чего я не понимаю, так это того, почему повторяются только контекст и список. У меня есть другой компонент, называемый головой, который рендерит только один раз (третья строка внизу на фотографии "голова"). Я подумал, что это может иметь какое-то отношение к моему useEffect внутри компонента list, но оно вызывается только тогда, когда есть изменение, которое не происходит на этом этапе.
UPDATE, включая компонент Header
в ответ на alverio:
import {DataContext} from 'context/DataContext'
const UserSelect = () => {
const {userList} = useContext(DataContext);
const {ChangeUser} = useContext(DataContext);
return(
<div>
<select defaultValue={'default'} onChange={(e)=>ChangeUser(e.target.value)}>
<option value='default' disabled>Select a user</option>
{userList.map(user=>(
<option key={user.id} value={user.id}>{user.name}</option>
))}
</select>
</div>
)
}
const ListSelect = () => {
console.log('ListSelect')
const {GetUserList} = useContext(DataContext);
const {userGroceryList} = useContext(DataContext);
const {userId} = useContext(DataContext);
const {ChangeList} = useContext(DataContext);
useEffect(()=>{
GetUserList();
},[userId])
return (
<div>
<select defaultValue={'default'} onChange={(e)=>{ChangeList(e.target.value)}}>
<option value='default' disabled >Select a grocery list</option>
{userGroceryList.map(list=>(
<option key={list.listId} value={list.listId}>{list.title}</option>))}
</select>
</div>
)
}
const ListAdd = () => {
const {WriteItem} = useContext(DataContext);
const {WriteList} = useContext(DataContext);
const {userId} = useContext(DataContext);
const {userTypeList} = useContext(DataContext);
const [item, setItem] = useState('');
const [product, setProduct] = useState('');
const [quantity, setQuantity] = useState('');
const [category, setCategory] = useState('');
const [type, setType] = useState('');
let measureCategory = ['Each', 'Lb', 'Oz', 'Fl Oz']
let dataCategory = ['Other','Beverages', 'Bakery', 'Canned Goods', 'Dairy', 'Baking Goods', 'Frozen Foods', 'Meat', 'Produce', 'Snacks'];
console.log('ListAdd')
return (
<div>
<div>
<input id="list" type="text" value={item} onChange={(e)=>setItem(e.target.value)}/>
<button type="button" onClick={(e)=>{WriteList(item)}}>New List</button>
</div>
<div>
<input type="text" value={product} onChange={(e)=>setProduct(e.target.value)}/>
<select defaultValue={'default'} onChange={(e)=>{setCategory(e.target.value)}}>
<option value='default' disabled >Select a category</option>
{userTypeList.map(ul=>ul.id===parseInt(userId)?(ul.categories.map((uc,index)=><option key={index} value={uc}>{uc}</option>)):null)}</select>
<br/>
<input type="number" value={quantity} onChange={(e)=>setQuantity(e.target.value)}/>
<select defaultValue={'default'} onChange={(e)=>{setType(e.target.value)}}>
<option value='default' disabled >Select a unit</option>
{measureCategory.map((mc,index)=><option key={index} value={mc}>{mc}</option>)}</select>
<button type="button" onClick={(e)=>{WriteItem(product,category,quantity,type)}}>New Item</button>
</div>
</div>
)
}
const Header = () => {
console.log('head')
return (
<div>
<div>
<UserSelect/>
</div>
<div>
<ListSelect/>
</div>
<div>
<ListAdd/>
</div>
</div>
)
}
export default Header;