plotly / plotly/react-plotly.js

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

Abierto
#171 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Lenguaje dominante
JavaScript
Estrellas
1.1k
Forks
138
Merge medio
3 d 2 h
PR fusionados (30 d)
4

Descripción

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;

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza con el componente App proporcionado y los componentes plotly_test y NavbarTop; después, reproduce el problema haciendo clic en un elemento de la leyenda y activando las actualizaciones de setState basadas en callbacks de Button2. Rastrea cómo react-plotly.js recibe las props actualizadas y determina por qué uirevision deja de conservar la visibilidad; se considera terminado cuando la visibilidad de la traza seleccionada permanece sin cambios después de esas actualizaciones.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
javascript, react
Área
data-visualization, frontend
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
35/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.