자바스크립트 질문입니다...(여러 사이트에 올려봤지만 그렇다 할 답이 안 나옵니다.)

이 질문을 여러 사이트에 질문을 해보았지만, 그렇다할 답변이 나오지는 않아서 여기까지 오게됐습니다.
음, exchange 부분에 문제가 있어 추천 받은 방법인 console.log()를 찍어 살펴 보아도 역시나 잘 모르겠네요… 혹시 몰라 조금이라도 관련된 부분의 코드는 전부 올려 봅니다.(어지럽다면 죄송합니다 ㅜㅜ 제가 볼때는 interactions.js 랑 Content.js 만 보시면 되는 것 같습니다ㅜㅜ)
혹시 문제가 바로 보이신다면 답변을 해주신다면 매우 감사하겠습니다. -

interactions.js

import Web3 from 'web3'
import {
  web3Loaded,
  web3AccountLoaded,
  tokenLoaded,
  exchangeLoaded,
  cancelledOrdersLoaded
} from './actions'
import Token from '../abis/Token.json'
import Exchange from '../abis/Exchange.json'

export const loadWeb3 = (dispatch) => {
  const web3 = new Web3(Web3.givenProvider || 'http://localhost:7545')
  dispatch(web3Loaded(web3))
  return web3
}

export const loadAccount = async (web3, dispatch) => {
  const accounts = await web3.eth.getAccounts()
  const account = accounts[0]
  dispatch(web3AccountLoaded(account))
  return account
}

export const loadToken = async (web3, networkId, dispatch) => {
    try {
        const token = new web3.eth.Contract(Token.abi, Token.networks[networkId].address)       
        dispatch(tokenLoaded(token))
        return token
    } catch (error) {
        console.log('Contract not deployed to the current network. Please select another network with Metamask.')
        return null
    }
} 

export const loadExchange = async (web3, networkId, dispatch) => {
  try {
    const exchange = new web3.eth.Contract(Exchange.abi, Exchange.networks[networkId].address)      
    dispatch(exchangeLoaded(exchange))
    return exchange
  } catch (error) {
    console.log('Contract not deployed to the current network. Please select another network with Metamask.')
    return null
  }
}
export const loadAllOrders = async (exchange, dispatch) => {
  // if (exchange) { // Make sure exchange has been defined
    // const exchange = new web3.eth.Contract(Exchange.abi, Exchange.networks[networkId].address)
     const cancelStream = await exchange.getPastEvents('Cancel', { fromBlock: 0, toBlock: 'latest' })
     // // await loadAllOrders(this.props.exchange, dispatch)
     console.log(cancelStream)
  }

App.js

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Navbar from './Navbar'
import Web3 from 'web3';   
import Content from './Content'
import { connect } from 'react-redux'
// import Token from '../abis/Token.json'
import {
  loadWeb3,
  loadAccount,
  loadToken,
  loadExchange
} from '../store/interactions'
import { contractsLoadedSelector } from '../store/selectors'

class App extends Component {
  componentWillMount() {    
    this.loadBlockchainData(this.props.dispatch)
  }

async loadBlockchainData(dispatch) {
    const web3 = loadWeb3(dispatch)
    const network = await web3.eth.net.getNetworkType()
    const networkId = await web3.eth.net.getId()
    const accounts = await loadAccount(web3, dispatch)
    const token = await loadToken(web3, networkId, dispatch)
    if(!token) {
      window.alert('Token smart contract not detected on the current network. Please select another network with Metamask.')
      return
    }
    const exchange = await loadExchange(web3, networkId, dispatch)
    if(!exchange) {
      window.alert('Exchange smart contract not detected on the current network. Please select another network with Metamask.')
      return
    }
  }

  render() {
    return (
      <div>
      <Navbar />
        { this.props.contractsLoaded ? <Content /> : <div className="content"></div> }
           </div>
           );
         }
       }

function mapStateToProps(state) {
  return {
    contractsLoaded: contractsLoadedSelector(state)
  }
}

export default connect(mapStateToProps)(App);

Content.js

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { exchangeSelector } from '../store/selectors'
import { loadAllOrders } from '../store/interactions'

class Content extends Component {
  componentWillMount() {
    this.loadBlockchainData(this.props.dispatch)
  }

  // async loadBlockchainData(exchange, dispatch) {
  async loadBlockchainData(dispatch) {
    await loadAllOrders(this.props.exchange, dispatch)
    // this.loadBlockchainData(this.props.exchange)
      // await loadAllOrders(exchange, dispatch)
  }

function mapStateToProps(state) {
  return {
    exchange: state.exchangeSelector
  }
}

export default connect(mapStateToProps)(Content)

selectors.js

import { get } from 'lodash'
import { createSelector } from 'reselect'

const account = state => get(state, 'web3.account')
export const accountSelector = createSelector(account, a => a)

const tokenLoaded = state => get(state, 'token.loaded', false)
export const tokenLoadedSelector = createSelector(tokenLoaded, tl => tl)

const exchangeLoaded = state => get(state, 'exchange.loaded', false)
export const exchangeLoadedSelector = createSelector(exchangeLoaded, el => el)

const exchange = state => get(state, 'exchange.contract')
export const exchangeSelector = createSelector(exchange, e => e)

export const contractsLoadedSelector = createSelector(
  tokenLoaded,
  exchangeLoaded,
  (tl, el) => (tl && el)
)

reducers.js

import { combineReducers } from 'redux';

function web3(state={}, action) {
    switch (action.type) {
        case 'WEB3_LOADED':
            return { ...state,  connection: action.connection }
        case 'WEB3_ACCOUNT_LOADED':
            return { ...state, account: action.account }
        default:
            return state
    }
}

function token(state = {}, action) {
  switch (action.type) {
    case 'TOKEN_LOADED':
      return { ...state, loaded: true, contract: action.contract }
    default:
      return state
  }
}

function exchange(state = {}, action) {
  switch (action.type) {
    case 'EXCHANGE_LOADED':
      return { ...state, loaded: true, contract: action.contract }
    case 'CANCELLED_ORDERS_LOADED':
      return { ...state, cancelledOrders: { loaded: true, data: action.cancelledOrders } }
    // case 'FILLED_ORDERS_LOADED':
    //   return { ...state, filledOrders: { loaded: true, data: action.filledOrders } }
    // case 'ALL_ORDERS_LOADED':
    //   return { ...state, allOrders: { loaded: true, data: action.allOrders } }
    default:
      return state
  }
}

우선 고자이신 것 에 심심한 위로의 말씀을 전합니다.

제가 잘은 모르지만, loadAllOrders 로 들어온 exchange 값이 49 라인이 실행될때, undefined 상태 인것이 직접적인 원인인거 같구요.

그렇게 된 원인으로는 … Content.js 에서 디스패치 펑션을 넘기시고는…

    this.loadBlockchainData(this.props.dispatch)

전혀 다른 프롭을 또불러 오시네요

await loadAllOrders(this.props.exchange, dispatch)

interaction.js 에 있는 바로는, exchange 가 펑션이여야 할것 같은데말이죠…

export const loadAllOrders = async (exchange, dispatch) => {
  // if (exchange) { // Make sure exchange has been defined
    // const exchange = new web3.eth.Contract(Exchange.abi, Exchange.networks[networkId].address)
     const cancelStream = await exchange.getPastEvents('Cancel', { fromBlock: 0, toBlock: 'latest' })
     // // await loadAllOrders(this.props.exchange, dispatch)
     console.log(cancelStream)
  }

리듀서도 안보이고… createSelector 도 뭔지 안보이고…

혹시 이거 본인 코드 맞으신가요?

아래 내용이 도움되실것 같읍니다.

행운을 빕니다!

3 Likes

앗! 고자에게 심심한 위로를 전해주셔서 감사합니다!!

리듀서를 깜빡했는지 생각은 못 했는데, 뒤늦게 올렸네요…

사실 리듀서 부분이 문제는 아닌지라…

아무튼 답장 너무 감사합니다… 여기 사이트에서 도움을 받게 될지는 전혀 몰랐습니다

이제 보니 exchange 가 펑션이 아니고, get어쩌구 를 가진 객체가 되는게 맞네요 :slight_smile:

그럼 저 커넥트가 제대로 동작 하고, 저 씰렉터에서 제대로 된거가 나오고 있는지 학인 하셔야 할것 같읍니다.

그리고, 기억이 가물한데, 리엑트 최근 버젼에서 몇몇 라이프 사이클 함수들을 디프리케잇 하는거 같던데, willMount가 포함이 되던가 모르겟네요. 그쪽도 살펴보시고, 대비를 하셔야…