d3 / d3-shape

Graphical primitives for visualization, such as lines and areas.
https://d3js.org/d3-shape
ISC License
2.47k stars 307 forks source link

d3 setting a mobx store variable errorMessage #105

Closed Shooshte closed 7 years ago

Shooshte commented 7 years ago

I am trying to integrate d3 with react and mobx. I have a store that gets some data from the server, and a computed that returns only part of that data (this is the only part of my code where I am setting this.showError, this.errorMessage):

import {observable, action, computed} from 'mobx';
import axios from 'axios'

import moment from "moment"

class store {
  // Error handling
  @observable showError = false
  @observable errorMessage = null

  // BitCoin data
  @observable priceHistory = []

  constructor() {
    this.getDailyData();
  }

  @action async getDailyData() {
    await axios.get('http://46.101.72.62:1337/prices/day').then((res) => {
      this.priceHistory = res.data
    }).catch((e) => {
      this.showError = true
      this.errorMessage = e.message
    })
  }

  @computed get getDailyPrices() {
    return this.priceHistory.map((price) => {
      return {
        price: price.last,
        timestamp: moment(price.timestamp).format('HH:MM')
      }
    })
  }

}

export default store;

Then I inject the store into my app, destructure the observables and print an error message if there is one, and if there is no error, I pass the data to a Price Chart component:

import React, {Component} from 'react';
import {toJS} from 'mobx'
import {observer, Provider} from 'mobx-react';

import PriceChart from './components/priceChart'

@observer
class App extends Component {

  render() {
    window.stores = toJS(this.props.stores)

    const {showError, errorMessage} = this.props.stores.store
    const dailyPrices = this.props.stores.store.getDailyPrices

    return (
      <Provider {...this.props.stores}>
        <div className="App">
          {showError
            ? <div><h3>{errorMessage}.</h3><p>There was an error loading the prices data, please try refreshing the page in a bit.</p></div>
            :
            <div>
              <PriceChart data={dailyPrices}/>
            </div>
          }
        </div>
      </Provider>
    );
  }
}

export default App;

This is the chart component that uses d3:

import React, {Component} from "react";
import {observer, inject} from "mobx-react";

import {line, select} from "d3"

@inject("store")
@observer
class PriceChart extends Component {
  constructor(props) {
    super(props)
    this.createLineChart = this.createLineChart.bind(this)
  }
  componentDidMount() {
    this.createLineChart()
  }
  componentDidUpdate() {
    this.createLineChart()
  }
  createLineChart() {
    const node = this.node

    const priceLine = line(this.props.data)
      .x((d) => d.timestamp)
      .y((d) => d.last)

    select(node).append(priceLine)
  }
  render() {
    return <svg ref={node => this.node = node} width={800} height={800}></svg>
  }
}

export default PriceChart;

Now what happens is that when the d3 library fails, the errorMessage gets set in the store. How is that possible?

A working example can be found here - https://github.com/Shooshte/bitgraph. Just pull, npm i, npm run start

mbostock commented 7 years ago

Please use Stack Overflow tag d3.js to ask for help. Although I make an effort to assist everyone that asks, I am not always available to provide help promptly or directly. Stack Overflow provides a better collaborative forum for self-help: tens of thousands of D3-related questions have already been asked there, and some answered questions may be relevant to you.

When asking for help, please include a link to a live example that demonstrates the issue, preferably on bl.ocks.org. It is often impossible to debug from code snippets alone. Isolate the issue and reduce your code as much as possible before asking for help. The less code you post, the easier it is for someone to debug, and the more likely you are to get a helpful response.

If you have a question about D3’s behavior and want to discuss it with other users, also consider the d3-js Google Group or joining the d3-js Slack.

Thank you! 🤗