0

I'm (very) new to React and am building a small web page as part of my learning process. My web page is a table of currencies (given using an API) and I should be able to delete and add currencies and revert to the table's original state.

Deleting as many as I want and then reverting a first time works fine. When I delete and then revert a second time - nothing happens.

My App's state has a 'shownData' attribute, holding the data currently presented in the table, and an 'initialData' attribute, holding the original data I should present when clicking 'revert'.

From my debugging process, it seems that clicking the 'revert' button ties 'initialData' to 'shownData', so that when reverting a second time nothing happens.

Here's the code for my main App component:

import React, { Component } from 'react';
import CurrencyTable from './currencyTable';
import SearchBar from './searchBar';
// import _ from 'lodash';
import RevertButton from './revertButton';
import logo from './logo.svg';
import './App.css';
import './bootstrap.min.css';

const API_KEY = '7312269b011ac267b5d9663c4a479c24';
const endpoint = 'latest';

class App extends Component {

    constructor(props){
        super(props);

        this.state={
            shownCountries: [],
            initialCountries: [],
            allData: [],
            shownData:[],
            initialData:[],
            value:'',
        }
    }

    componentDidMount(){
        this.setState({shownCountries: ['EUR', 'ILS', 'USD', 'GBP', 'AUD']});
        this.setState({initialCountries: ['EUR', 'ILS', 'USD', 'GBP', 'AUD']});

        // localStorage.setItem('shownC', JSON.stringify(this.shownCountries));
        const cachedCountries = localStorage.getItem('shownC');
        if (!cachedCountries)
            localStorage.setItem('shownC', JSON.stringify(this.state.shownCountries));
        else
            this.setState({shownCountries: JSON.parse(cachedCountries)});

        fetch(`http://data.fixer.io/api/${endpoint}?access_key=${API_KEY}`)
            .then(results => {
                return results.json();
            })
            .then(result => {
                let rates = result.rates;
                let shownData = [];
                let initialData = [];
                let allData = [];
                let i = 0;
                let j = 0;
                let k = 0;

                //check for saved data in local storage:
                Object.keys(rates).forEach(key => {
                    if (this.state.shownCountries.indexOf(key) > -1){
                        shownData[j] = {rate: key, value: rates[key], button: "btn btn-danger red"};
                        j++;
                    }
                    if (this.state.initialCountries.indexOf(key) > -1){
                        initialData[k] = {rate: key, value: rates[key], button: "btn btn-danger red"};
                        k++;
                    }
                    allData[i] = {rate: key, value: rates[key], button: "btn btn-danger red"};
                    i++;
                })

                this.setState({allData: allData, initialData: initialData, shownData: shownData});
            })
    }

    findValue(rate){
        for (let i=0; i<this.state.allData.length; i++){
            if (this.state.allData[i].rate === rate)
                return this.state.allData[i].value;
        }
    }

    handleChangeValue = value => {
        let newRateObj = {rate: value, value: this.findValue(value), button: "btn btn-danger red"};
        this.setState({
            shownData: this.state.shownData.concat([newRateObj])
        });
        this.state.shownCountries.concat([value]);
        localStorage.setItem('shownC', JSON.stringify(this.state.shownCountries));
    }

    handleRevertClick = () => {
        console.log(this.state.initialData);
        localStorage.setItem('shownC', JSON.stringify(this.state.initialCountries));
        this.setState({shownData: this.state.initialData});
        console.log(this.state.initialData);
    };

    saveToLocalStorage(data) {
        localStorage.setItem('shownC', JSON.stringify(this.getShownCList(data)));
    }

    getShownCList(data){
        let shownC = [];
        for (let i=0;i<data.length;i++){
            shownC.push(data[i].rate);
        }
        // console.log(shownC);
        return shownC;
    }


    render() {
        console.log("initialData is:");
        console.log(this.state.initialData);
        if (this.state.initialData.length===0)
            return 'loading...';
        return (
            <div className="headDiv">
                <div className="App">
                    <header className="App-header">
                        <img src={logo} className="App-logo" alt="logo" />
                        <h1 className="App-title">Niki's React Currency App</h1>
                    </header>
                </div>
                <div className="mainDiv">
                    <div className="col">
                        <div className="col-lg-6 currencyTableContainer">
                            <CurrencyTable
                                data = { this.state.shownData }
                                saveToLS= {(data) => {
                                    this.saveToLocalStorage(data)}}/>
                        </div>
                        <div className="col-lg-6 searchAndRevertContainer">
                            <div className="row">
                                <div className="row-md-4">
                                    <SearchBar
                                        value={this.state.value}
                                        allData = { this.state.allData }
                                        onChangeValue={this.handleChangeValue}/>
                                </div>
                                <div className="row-md-4 revertButton">
                                    <RevertButton
                                        onClick={this.handleRevertClick}/>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

            </div>

        );
    }
}

export default App;

And here's the code for the onClick function in the table component, that deletes a row (after which initialData seems to go wrong):

onRemoveClick(rate){
    const newShownData = this.state.myTableData;
    let index = _.findIndex(newShownData, {rate: rate});
    if (index>-1)
        newShownData.splice(index, 1);
    this.setState({myTableData: newShownData});
    this.props.saveToLS(this.state.myTableData);
}

I'm super lost, help? :)

nikit
  • 1
  • 1
  • Possible Duplicate of [setState doesn't update the state immediately](https://stackoverflow.com/questions/41278385/setstate-doesnt-update-the-state-immediately/41278440#41278440) – Shubham Khatri Apr 25 '18 at 19:38
  • `this.setState({myTableData: newShownData}, () => { this.props.saveToLS(this.state.myTableData); });` – Shubham Khatri Apr 25 '18 at 19:39
  • The state changes according to initialData - but initialData has changed, which it shouldn't have. – nikit Apr 25 '18 at 19:43
  • You are actually updating initialData when you do `this.props.saveToLS(this.state.myTableData);` , what exactly do you want to achieve – Shubham Khatri Apr 25 '18 at 19:53
  • Why does that update initialData? All I do is save the data to local storage. I want initialData to never change, so that when I revert I always revert to the same list of currencies. – nikit Apr 25 '18 at 19:57

1 Answers1

0

Solved by creating a deep copy of initialData before giving its value to shownData:

...
var temp = JSON.parse(JSON.stringify(this.initialData))
this.setState({shownData: temp});
...
nikit
  • 1
  • 1