简体   繁体   中英

How to use useEffect to get data from redux using useSelector @redux/toolkit?

i am working on a pet-shop react Dapp, at certain point the requirement is to auto refresh pet adopters list.. so for this i have tried useEffect with useSelector to get the data from store... but the problem is it is running and i can see it in my console but it doesn't refresh the list. to get the updated list i need to refresh the page which is not a good idea.

Problem

i open two same UI tabs, on UI one i am adopting a pet it updates the adopters list and hide the button of adopt pet, but the same time second UI doesn't updated automatically, if i need to see any updates i must refresh the UI(page) to get updates.

i want it to just refresh the list without refreshing the whole page, only a specific part of the page updates no need to refresh the whole page...

adoptionSlice.js

import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import Web3 from "web3";
import Adoption from '../contracts/Adoption'

export const initWeb3 = createAsyncThunk(
    'InitWeb3',
    async (a, thunkAPI) => {
        console.log('initWeb3 a: ', a)
        console.log('initWeb3 thunkapi: ', thunkAPI)
        console.log('initWeb3 dispatch: ', thunkAPI.dispatch)
        try {

            if (Web3.givenProvider) {
                const web3 = new Web3(Web3.givenProvider)
                await Web3.givenProvider.enable();
                web3.eth.handleRevert = true;

                const networkId = await web3.eth.net.getId();
                const network = Adoption.networks[networkId];
                const contract = new web3.eth.Contract(Adoption.abi, network.address)
                const addresses = await web3.eth.getAccounts()
                thunkAPI.dispatch(loadAdopters({
                    contract: contract,
                    address: addresses[0]
                }))
                console.log(addresses)

                return {
                    web3: web3,
                    contract: contract,
                    address: addresses[0],
                }
            }
            else {
                console.log('Error In Loading Web3')
            }
        }
        catch (err) {
            console.log('Error In Loading')
        }
    }
)

// export const loadAdopters = createAsyncThunk(
//     'LoadAdopters',
//     async (a, thunkAPI) => {
//         console.log('in loadAdopters a = ', a);
//         console.log('in loadAdopters thunkApi = ', thunkAPI);
//         console.log('in loadAdopters thunkApi state = ', thunkAPI.getState());
//         const contract = thunkAPI.getState().adoptReducer.contract;
//         console.log('loadadopters contract = ', contract);
//         const adopterList = await contract.methods.getAdopters().call()
//         return adopterList
//     }
// )
export const loadAdopters = createAsyncThunk(
    "LoadAdopters",
    async(data,thunkAPI)=>{
        const adopterList = await data.contract.methods.getAdopters().call();
        return adopterList;
    }
)

const adoptSlice = createSlice({
    name: 'AdoptSlice',
    initialState: {
        web3: null,
        contract: null,
        address: null,
        adopters: [],
        adoptInProgress: false,
        adopError: false,
        adoptErrorMessage: '',
        releasingPetStatus: false,
        releasePetError: '',
        releaseErrorMessage: ''
    },
    reducers: {
        adopt: () => { }
    },
    extraReducers: {
[initWeb3.fulfilled]: (state, action) => {
            console.log("In fullfil = ", state);
            console.log("In fullfil = ", action);
            state.web3 = action.payload.web3;
            state.contract = action.payload.contract;
            state.address = action.payload.address;
        },
        [loadAdopters.fulfilled]: (state, action) => {
            state.adopters = action.payload
        },
}

export const adopReducer = adoptSlice.reducer;
export const { adopt } = adoptSlice.actions;

adoptionSlice.js for loading web3 and to get loadAdopters

App.js

function App() {
  const dispatch = useDispatch();
  
  const web3 = useSelector((state)=>{
    console.log("state in app= ",state);
    return state.adoptReducer.web3
  })
 
  useEffect(()=>{
    dispatch(initWeb3());
  // eslint-disable-next-line react-hooks/exhaustive-deps
  },[])

  return (
    <div>
      <PetList></PetList>
    </div>
  );
}

export default App;

Adopter.js

import React from 'react'
import { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { loadAdopters } from '../store/adoptSlice'

export const Adopters = () => {
    const dispatch = useDispatch()
    const adoptersList = useSelector((state) => {
        return state.adoptReducer.adopters
    })

    useEffect(() => {

        const interval = setInterval(() => {
            dispatch(loadAdopters())
            console.log('updated')
        }, 2000)
        return () => clearInterval(interval)
    }, [])
    return (
        <div>
            <div>Adopters List</div>
            <div>
                {
                    adoptersList.map((list, index) => (
                        list !== '0x0000000000000000000000000000000000000000' ? <div key={index}>index {index} : {list}</div> : null
                    ))
                }
            </div>
        </div>
    )
}

Adopter.js to get the list of adopters from store

这是收养者名单

I guess what you are trying to achieve is not possible with what you have explained. There are mainly two problems.

  • When you open a same react app on two different tabs, its essentiality two different instance of the app, which shares nothing in common. Each of it has its own state, redux,etc.

  • What can be understood from your problem is you want that whenever an action is done that changes/updates your value in some DB, you want it to be reflected across other users. This is not possible if you are NOT

  • a. continuosly calling the api explicitly,

    b. using some libraries that silently calls the api for you and update the state (eg, SWR)

    c. using any pub/sub model (eg signalR)

So, you should try to think and solve the second problem first, which will automatically solve the first one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM