React redux action for Twitch extension

Viewed 112

I am having some problems with the dispatch of an action under Redux.

I have applied the different tutorials to the letter, but yet this does not take, I always get an empty table in my props.

Here is my code:

Config.js

import React from "react"
import ReactDOM from "react-dom"

import { Provider } from 'react-redux'
import store from './store'

import ConfigPage from "./components/ConfigPage/ConfigPage"

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={store}>
    <ConfigPage />
  </Provider>,
  rootElement
);

Store

    import {createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'

import rootReducer from './reducers'

import { fetchWalletAddress } from './actions/index'


const store = createStore(rootReducer, applyMiddleware(thunk))

store.dispatch(fetchWalletAddress());

export default store;

Reducer wallet.js

import { GET_WALLET_ADDRESS } from "../actions/actionTypes.js";

const initialState = {
    wallet:[]
}

export default function(state = initialState, action){
    switch(action.type){
        case GET_WALLET_ADDRESS:
            return [ ...state, ...action.payload];
        default: 
            return state;
    }
}

My action :

import {GET_WALLET_ADDRESS} from './actionTypes.js'
import axios from 'axios'

const apiUrl = 'https://api.elrond.com/accounts/erd15qltd5ccalm5smmgdc5wnx46ssda3p32xhsz4wpp6usldq7hq7xqq5fmn6';


export const fetchWalletAddress = () => {
    return (dispatch) => {
        return axios.get(apiUrl)
            .then(response => {
                return response.data
            })
            .then(data => {
                dispatch({
                    type: GET_WALLET_ADDRESS,
                    payload: data
                })
            })
            .catch(error => {
                throw (error);
            });
    };
};

And for finish, my Configpage.js

import React from 'react'
import Authentication from '../../util/Authentication/Authentication'
import './Config.css'
import { connect } from 'react-redux'

import { fetchWalletAddress } from '../../actions/index'

class ConfigPage extends React.Component{
    constructor(props){
        super(props)
        this.Authentication = new Authentication()

        //if the extension is running on twitch or dev rig, set the shorthand here. otherwise, set to null. 
        this.twitch = window.Twitch ? window.Twitch.ext : null
        this.state={
            finishedLoading:false,
            theme:'light',
            isVisible:true,
            wallet_address:'erd15qltd5ccalm5smmgdc5wnx46ssda3p32xhsz4wpp6usldq7hq7xqq5fmn6'
        }
        this.walletAddressHandler = this.walletAddressHandler.bind(this);
        this.onSubmitForm = this.onSubmitForm.bind(this);
    }

    walletAddressHandler(event){
        this.setState({
            [event.target.name]:event.target.value
        });
    }

    onSubmitForm(){
        fetchWalletAddress();
        this.twitch.rig.log(this.props.wallet)
    }

    contextUpdate(context, delta){
        if(delta.includes('theme')){
            this.setState(()=>{
                return {theme:context.theme}
            })
        }
    }

    visibilityChanged(isVisible){
        this.setState(()=>{
            return {
                isVisible
            }
        })
    }

    componentDidMount(){

        this.twitch.rig.log(this.props.wallet)

        if(this.twitch){
            this.twitch.onAuthorized((auth)=>{
                this.Authentication.setToken(auth.token, auth.userId)
                if(!this.state.finishedLoading){
                    // if the component hasn't finished loading (as in we've not set up after getting a token), let's set it up now.

                    // now we've done the setup for the component, let's set the state to true to force a rerender with the correct data.
                    this.setState(()=>{
                        return {finishedLoading:true}
                    })
                }
            })

            this.twitch.listen('broadcast',(target,contentType,body)=>{
                this.twitch.rig.log(`New PubSub message!\n${target}\n${contentType}\n${body}`)
                // now that you've got a listener, do something with the result... 

                // do something...

            })

            this.twitch.onVisibilityChanged((isVisible,_c)=>{
                this.visibilityChanged(isVisible)
            })

            this.twitch.onContext((context,delta)=>{
                this.contextUpdate(context,delta)
            })
        }
    }

    componentWillUnmount(){
        if(this.twitch){
            this.twitch.unlisten('broadcast', ()=>console.log('successfully unlistened'))
        }
    }

    filterFloat(value) {
        if (/^(\-|\+)?([0-9]+(\.[0-9]+)?|Infinity)$/
          .test(value))
          return Number(value);
      return NaN;
    }
    
    render(){
        if(this.state.finishedLoading && this.state.isVisible){
            return (
                <div className="App">
                    <div className={this.state.theme === 'light' ? 'App-light' : 'App-dark'} >
                        <p>Add your wallet address</p>

                        <input
                            name="wallet_address"
                            type="text"
                            onChange={this.walletAddressHandler}
                            value={this.state.wallet_address}>
                        </input>
                        <p>{this.props.wallet.username}</p>
                        <button OnClick={this.onSubmitForm}>Try it</button>
                        <ul>
                            {this.state.wallet ? String((Number(this.state.wallet.balance) * Math.pow(10, -18)).toFixed(4)) : null}
                        </ul>
                    </div>
                </div>
            )
        }else{
            return (
                <div className="App">
                </div>
            )
        }

    }
}


const mapStateToProps  = state => {
    return {
        wallet: state.wallet
    }
};

export default connect(mapStateToProps, null)(ConfigPage);

thank you in advance for your help

1 Answers

You do not need to dispatch fetchWalletAddress while creating store, you can do that in the component. Also when you call fetchWalletAddress in the component, make sure to use the function that you make available to component via mapDispatchToProps argument of connect otherwise it wouldn't affect the redux store

Another thing you must do is to not use the updated redux value in the same function call since it takes a render cycle for it to reflect the updated change

store.js

import {createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'

import rootReducer from './reducers'


const store = createStore(rootReducer, applyMiddleware(thunk))


export default store;

Configpage.js

...

componentDidMount(){
    this.props.fetchWalletAddress();
    this.twitch.rig.log(this.props.wallet)

    if(this.twitch){
        this.twitch.onAuthorized((auth)=>{
            this.Authentication.setToken(auth.token, auth.userId)
            if(!this.state.finishedLoading){
                // if the component hasn't finished loading (as in we've not set up after getting a token), let's set it up now.

                // now we've done the setup for the component, let's set the state to true to force a rerender with the correct data.
                this.setState(()=>{
                    return {finishedLoading:true}
                })
            }
        })

        this.twitch.listen('broadcast',(target,contentType,body)=>{
            this.twitch.rig.log(`New PubSub message!\n${target}\n${contentType}\n${body}`)
            // now that you've got a listener, do something with the result... 

            // do something...

        })

        this.twitch.onVisibilityChanged((isVisible,_c)=>{
            this.visibilityChanged(isVisible)
        })

        this.twitch.onContext((context,delta)=>{
            this.contextUpdate(context,delta)
        })
    }
}

...
componentDidUpdate(prevProps) {
    if (!_.isEqual(prevProps.wallet, this.props.wallet)) {
       this.twitch.rig.log(this.props.wallet)
    }
}
...

onSubmitForm(){
    this.props.fetchWalletAddress();// use action from props
}
...
const mapDispatchToProps = {
    fetchWalletAddress,
}
const mapStateToProps  = state => {
    return {
        wallet: state.wallet
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(ConfigPage);
Related