plotly / plotly/react-plotly.js

uirevision not preserving the trace's visibility (legend click)

Aberta
#171 0 comentários 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

Linguagem predominante
JavaScript
Estrelas
1.1k
Forks
138
Merge médio
3d 2h
PRs com merge (30d)
4

Descrição

When adding the below line to the layout [1], one would expect that the chart preserves the trace's visibility even after the data is reload, or other elements of a webapp change.

Whilst it works nice and clean in a simple test, in an almost empty react project, it doesn't seem to work well in a medium sized app, with dozens of Components and states.

In my specific example, it is enough for someone to change the navigation bar dropdowns, which trigger an event changing the state of App.js, where the charts originate, too. In the very same second when the dropdown changes its value, the charts lose their 'memory' of what was previously selected, and revert back to their original state.

I'll see if I can reproduce this in a sharable code-pen, but perhaps someone already encountered this issue?

Am using react-plotly 2.4.0 with plotly.js 1.48.0

**1**
uirevision: 'true'

Was able to recreate it. ui revision seems to be failing when callbacks are used in reacts setState.
Clicking 'Button2' twice, will reset the selected traces to their default. Simply removing the callback (which does not affect the plot) makes it behave as intended again.

import React, { Component } from 'react';
import './App.css';
import MyPlot from "./plotly_test";
import NavbarTop from "./NavbarTop";


class App extends Component {
  constructor() {
    super();
    this.onClickButton = this.onClickButton.bind(this);
    this.onClickButton2 = this.onClickButton2.bind(this);
    this.state = {
      myID: 1,
      countries: {names: ['Alal', 'lqwel', 'qpweok'], labels: ['loqwe', 'qwoel', 'qlweo']},
      country: 'Poland',
    }
  };


  onClickButton() {
    this.setState({myID: this.state.myID + 1})
    this.changeCountry = this.changeCountry.bind(this);
    var labels = this.state.countries.labels
    this.setState({
      labels: labels.push('SomeLabel')
    })
  }

  onClickButton2() {
    this.setState({
      country: "SomeCountry",
    }, ()=>{
      this.setState({
        country: 'Yet Another'
      })
    })
  }

  changeCountry = (value, callback) => {
    this.setState({
      country: value,
    }, () => {
      callback(value)
    })
  };

  getCharts() {
    let components = [];
    components.push((<MyPlot id={this.state.myID}/>));
    return components
  }

  render() {
    let charts = this.getCharts();

    return (
      <div>
        <h1>{this.state.country}</h1>
        <NavbarTop callbackChange={this.changeCountry}/>

        <div className="App">
          {charts}
          <button
            onClick={this.onClickButton}
          > Button1
          </button>
          <button
            onClick={this.onClickButton2}
          > Button2
          </button>
        </div>
      </div>
    )
  }
}

export default App;

Navbar:

import React, { Component } from 'react';

class NavbarTop extends Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    this.props.callbackChange(event.target.value, (something) => {
      console.log(something);
    })
  }

  render() {
    return (
      <div>
        <nav>
          <nav>
            <select name="countries" id="countries"
                    onChange={this.handleChange} value={'PL'}>
              <option value='DE'>Germany</option>
              <option value='FR'>France</option>
              <option value='ES'>Spain</option>
              <option value='UK'>United Kingdom</option>
            </select>
          </nav>
        </nav>
      </div>
    );
  }
}

export default NavbarTop;

plotly_test:


import React, {Component} from 'react'
import Plot from 'react-plotly.js'

class MyPlot extends Component {

  render() {
    const rand = () => 1;
    var x = [1, 2, 3, 4, 5];
    const new_data = (trace) => Object.assign(trace, {y: x.map(rand)});

// add random data to three line traces
    var data = [
      {mode:'lines', line: {color: "#b55400"}},
      {mode: 'lines', line: {color: "#393e46"}},
      {mode: 'lines', line: {color: "#222831"}}
    ].map(new_data);

    var layout = {
      title: this.props.id,
      uirevision:'true',
      xaxis: {autorange: true},
      yaxis: {autorange: true}
    };

    return (
      <div>
        <Plot
        layout={layout}
        data={data}
        />
      </div>
    );
  }
}

export default MyPlot;

Guia de contribuição

Nenhum guia de contribuição indexado para este repositório

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Comece com o componente App fornecido e com os componentes plotly_test e NavbarTop e, em seguida, reproduza o problema clicando em um item da legenda e acionando as atualizações de setState baseadas em callback de Button2. Rastreie como react-plotly.js recebe as Props atualizadas e determine por que uirevision deixa de preservar a visibilidade; a tarefa estará concluída quando a visibilidade da trace selecionada permanecer inalterada após essas atualizações.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
javascript, react
Domínio
data-visualization, frontend
Tipo de issue
Bug
Dificuldade
4/5
Tempo estimado
3-5 dias
Status de atividade
Estagnada
Clareza
Razoavelmente clara
Facilidade para iniciantes
35/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.