Material UI linear progress animation when using data

℡╲_俬逩灬. 提交于 2020-03-24 00:51:59

问题


The docs at material ui for reactJS proposes this sample code for determinate progress bars.

export default class LinearProgressExampleDeterminate extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            completed: 0,
        };
    }

    componentDidMount() {
        this.timer = setTimeout(() => this.progress(5), 1000);
    }

    componentWillUnmount() {
        clearTimeout(this.timer);
    }

    progress(completed) {
        if (completed > 100) {
            this.setState({completed: 100});
        } else {
            this.setState({completed});
            const diff = Math.random() * 10;
            this.timer = setTimeout(() => this.progress(completed + diff), 1000);
        }
     }

     render() {
        return (
            <LinearProgress mode="determinate" value={this.state.completed} />
        );
     }
}

This creates a loading animation until bar is full. I am trying to modify it to use data from a json file so that it stops at the value that I specified for it in each json item. I am getting that part right. That was the easy part. But the animation fails because the animation is scripted using the value of completed in the constructor's state. And it is also located outside of my data.map so I can seem to find the way to make it read the value in the json file so it can se it for it's timeout function. :(

This is what I have (reduced)

JSON

exports.playerItems = [
    {
        id: 283,
        completed: "100",
    }
    {
        id: 284,
        completed: "70",
    }
    {
        id: 285,
        completed: "20",
    }

    ...

    {
        id: 295,
        completed: "50",
    }
]

Data injection

import PLAYERS from 'data/players.js';
const playersData = PLAYERS['playerItems'];

And my table is mapped

<Table>
   {playersData.map((row, index) => (
       <TableRow id={row.name} key={index}>
           <TableRowColumn>

                <LinearProgress
                    mode="determinate"
                    value={row.completed} />

            </TableRowColumn>
       </TableRow>
   ))}
</Table>

How can I modify the progress() function so that it animates the value given to the LinearProgress?

Thanks in advance


回答1:


You can apply a state change to an array of player data and continually update the array in increments until all of the players have rendered.

First, start from zero:

  constructor(props) {
    super(props);
    this.state = {
      playersData: data.map(item => ({ ...item, completed: 0}))
    };
  };

Then initiate progress at mount:

  componentDidMount() {
    this.timer = setTimeout(() => this.progress(5), 100);
  }

Update until each player has reached 100%:

  progress(completion) {
    let done = 0;
    this.setState({
      playersData: data.map((item, i) => {
        const { completed: current } = this.state.playersData[i];
        const { completed: max } = item;
        if (current + completion >= max) {
          done += 1;
        }
        return {
          ...item,
          completed: Math.min(current + completion, max),
        };
      }),
    });
    if (done < data.length) {
      this.timer = setTimeout(() => this.progress(5), 100);
    }
  }

Adjust the delay and increment as you see fit. The limitation is that you need all of the player data that will be rendered and it needs to be in state as an array that is updated in a single setState

Here is a working example on codesandbox.



来源:https://stackoverflow.com/questions/47929977/material-ui-linear-progress-animation-when-using-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!