Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update state in specific rows in a table ReactJS

Tags:

reactjs

I have icons in a table setup so that when an icon is clicked, a different icon is rendered. Now this works fine but I want to re-render a different icon for that specific row in the row that I clicked as opposed to re-rendering a different icon in every row. No idea as to how I would go about doing this. Here is my code:

import React from 'react';
import StarBorder from '@material-ui/icons/StarBorder';
import Star from '@material-ui/icons/Star';
import axios from 'axios';

class Test extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            starIcon: true,
            data: [],
        }
    }

    componentDidMount() {

        axios.get('https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=true')
            .then(res => {
                const data = res.data;
                this.setState({  data: data})
            })
    }

    handleClick = () => {
        this.setState(prevState => ({
          starIcon: !prevState.starIcon
        }));
      }

    render() {
        return (
        <div>
            <table border="1">
                <thead>
                    <tr>
                    <td>Rank</td>
                    <td>Name</td>
                    <td>Price</td>
                    </tr>
                </thead>
                <tbody>
                {this.state.data.map((n) => {
                    return (
                        <tr>
                        <td> <span onClick={() => this.handleClick()}> {this.state.starIcon ? <StarBorder/> : <Star /> } </span> </td>
                        <td>{n.name}</td>
                        <td>{n.current_price}</td>
                        </tr>
                    );
                    })}
                </tbody>
            </table>
        </div>
        );
    }
}

export default Test;
like image 693
ShaneOG97 Avatar asked Aug 12 '19 14:08

ShaneOG97


People also ask

How do you update part of state in React?

To update our state, we use this. setState() and pass in an object. This object will get merged with the current state. When the state has been updated, our component re-renders automatically.

How do I edit a row in React table?

In your column array that you pass into react table you need to create a button who's onClick function takes a callback to edit your data to add an isEditing: true so you will handle turning the row to edit mode from outside of the table.

Can we directly modify state in React?

React will then look at the virtual DOM, it also has a copy of the old virtual DOM, that is why we shouldn't update the state directly, so we can have two different object references in memory, we have the old virtual DOM as well as the new virtual DOM.


1 Answers

The way I see it, you need to either duplicate your starIcon boolean in an array that has the same length as your data array, or integrate your boolean in your data array. Here's a proposition for the second option :

import React from 'react';
import StarBorder from '@material-ui/icons/StarBorder';
import Star from '@material-ui/icons/Star';
import axios from 'axios';

class Test extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: [],
        }
    }

    componentDidMount() {

        axios.get('https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=true')
            .then(res => {
                const data = res.data;
                this.setState({  data: data.map(x => ({...x, starIcon: true}) ) })
            })
    }

    handleClick = (i) => {
        this.setState(prevState => ({
          data: prevState.data.map((x, key) => (key === i ? {...x, starIcon: !x. starIcon} : x) )
        }));
      }

    render() {
        return (
        <div>
            <table border="1">
                <thead>
                    <tr>
                    <td>Rank</td>
                    <td>Name</td>
                    <td>Price</td>
                    </tr>
                </thead>
                <tbody>
                {this.state.data.map((n, i) => {
                    return (
                        <tr>
                        <td> <span onClick={() => this.handleClick(i)}> {n.starIcon ? <StarBorder/> : <Star /> } </span> </td>
                        <td>{n.name}</td>
                        <td>{n.current_price}</td>
                        </tr>
                    );
                    })}
                </tbody>
            </table>
        </div>
        );
    }
}

export default Test;

Hope it helps

like image 181
SoufianeL Avatar answered Oct 23 '22 15:10

SoufianeL