reactjs компонент вызывается несколько раз - PullRequest
0 голосов
/ 15 февраля 2020

Я работаю с Reactjs, чтобы получить информацию из базы данных и затем отобразить ее в формате PDF. Я продолжаю сталкиваться с проблемами, и я думаю, что я сузил его до того, откуда он исходит, но не уверен, что является причиной проблемы.
На следующем рисунке вы заметите, что у меня есть повтор трех журналов консоли, которые это «список» и «провайдер». enter image description here

Код основного приложения:

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...