I am sure I'm missing something obvious but I cannot get the the results returned from an API to show up in the table I have. The state variable maps to the console how it is supposed to but won't show up in the table. I moved the component into the same file to eliminate the possibility that it was due to improperly sending the state to the child component but that doesn't seem to be the case. My code is below:
import React, { useState, useEffect } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import './GrowthCalculator.css';
import { Container, CardDeck, Card, Row, Col, Badge, Table } from 'react-bootstrap';
import axios from 'axios';
import FixedCard from '../components/fixedAssets/FixedCard';
import StockCard from '../components/stocks/StockCard';
import Navigation from '../components/Navigation';
import AssetContext from '../context/AssetContext.js';
import HowTo from '../components/HowTo';
const growthCalculator = (props) => {
const [fixedState, setFixedState] = useState([]);
const [stockState, setStockState] = useState([]);
const assets = [fixedState, setFixedState, stockState, setStockState];
let stocks = stockState;
let fixed = fixedState;
useEffect(() => {
stocks = stockState;
fixed = fixedState;
//Would useRef() fix my issue?
}, [fixedState, stockState]);
const getResult = (event) => {
const form = event.currentTarget;
event.preventDefault();
event.stopPropagation();
const assets = fixedState;
let principle = form.principle.value;
const iLength = form.investmentLength.value / 12;
let compound = form.compound.value
let rate = form.rate.value;
let amount;
if (form.amount) {
amount = form.amount.value;
principle = principle * amount;
}
if (isNaN(rate) || rate < 0) {
alert("As much fun as it would be to calculate the result with \"" + rate + "\", it can't be done. Please enter a valid number");
} else {
if (compound === "Monthly") {
compound = 12;
} else if (compound === "Annually") {
compound = 1;
} else if (compound === "Quarterly") {
compound = 4;
} else {
compound = 365;
}
const headers = {
'Content-type': 'application/json',
'Access-Control-Allow-Origin': 'localhost:3000/',
'Access-Control-Allow-Methods': 'POST',
}
const body = {
principle: principle,
interestRate: rate,
iLength: iLength,
compoundFrequency: compound
}
axios.post("http://localhost:8080/compound-calculator/savings", body, { headers })
.then(res => {
assets.push(res.data);
setFixedState(assets);
fixedState.map(asset => console.log(asset));
});
}
}
const getStockPrice = (event) => {
const form = event.currentTarget;
event.preventDefault();
event.stopPropagation();
const roi = form.roi.value;
const mos = form.mos.value;
const equity = form.equity.value * 1000;
const shares = form.shares.value * 1000000;
if (roi <= 0) {
alert("You probably don't want to make nothing on your investment");
} else if (mos < 0 || mos > 50) {
alert("Margin of safety must be between 0 (I don't recommend this) and 50");
} else if (shares <= 0) {
alert("Are you sure that's the correct number of shares?");
} else {
const headers = {
'Content-type': 'application/json',
'Access-Control-Allow-Origin': 'localhost:3000/',
'Access-Control-Allow-Methods': 'POST',
}
let body;
if (form.fcf1) {
let fcf1; let fcf2; let fcf3; let fcf4; let fcf5;
fcf1 = form.fcf1.value;
fcf2 = form.fcf1.value;
fcf3 = form.fcf1.value;
fcf4 = form.fcf1.value;
fcf5 = form.fcf1.value;
const fcf = [fcf5, fcf4, fcf3, fcf2, fcf1];
body = {
desiredReturn: roi,
currentEquity: equity,
marginOfSafety: mos,
shares: shares,
freeCashFlow: fcf
}
axios.post("http://localhost:8080/compound-calculator/stock-fcf", body, { headers })
.then(res => {
stocks.push(res.data);
setStockState(stocks);
stockState.map(asset => console.log(asset));
});
} else {
let cf1; let cf2; let cf3; let cf4; let cf5;
let capex1; let capex2; let capex3; let capex4; let capex5;
cf1 = form.cf1.value;
cf2 = form.cf2.value;
cf3 = form.cf3.value;
cf4 = form.cf4.value;
cf5 = form.cf5.value;
capex1 = form.capex1.value;
capex2 = form.capex2.value;
capex3 = form.capex3.value;
capex4 = form.capex4.value;
capex5 = form.capex5.value;
const cf = [cf5, cf4, cf3, cf2, cf1];
const capex = [capex5, capex4, capex3, capex2, capex1];
body = {
desiredReturn: roi,
currentEquity: equity,
marginOfSafety: mos,
shares: shares,
cashFlows: cf,
capitalExpenditures: capex
}
axios.post("http://localhost:8080/compound-calculator/stock", body, { headers })
.then(res => {
stocks.push(res.data);
setStockState(stocks);
stockState.map(asset => console.log(asset));
});
}
}
}
return (
<main>
<AssetContext.Provider value={[...assets]}>
<Container>
<br></br>
<Navigation />
</Container>
<br></br>
<HowTo />
<br></br>
<CardDeck>
<FixedCard getResult={getResult} />
<StockCard getStock={getStockPrice} />
</CardDeck>
<br></br>
<Container>
<Card body>
<Card.Title>
Result card
</Card.Title>
<br></br>
<hr></hr>
<section>
<Row>
<Col>
<p><Badge variant="secondary">Compounding assets</Badge></p>
<Table striped borderless hover size="sm" variant="secondary" responsive>
<thead>
<tr>
<th>
#
</th>
<th>
Principle
</th>
<th>
length
</th>
<th>
End value
</th>
</tr>
</thead>
<tbody>
//What am I missing here?
{fixed.map((asset, index) => (
<tr>
<td>
{index + 1};
</td>
<td>
${asset.principle}
</td>
<td>
{asset.iLength} yrs
</td>
<td>
${asset.endValue}
</td>
</tr>))
}
</tbody>
</Table>
</Col>
/*
* Below here is not yet implemented
*/
<Col>
<p><Badge variant="secondary">Stocks</Badge></p>
<Table striped borderless hover size="sm" variant="secondary" responsive>
<thead>
<tr>
<th>
#
</th>
<th>
Ticker
</th>
<th>
Market
</th>
<th>
Discounted
</th>
</tr>
</thead>
<tbody>
{/* <tr>
<td>
Ticker
</td>
<td>
Fair price
</td>
<td>
Discount price
</td> */}
{/* </tr> */}
</tbody>
</Table>
</Col>
</Row>
</section>
</Card>
</Container>
<br></br>
</AssetContext.Provider>
</main>
);
}
export default growthCalculator;
The component is huge. After I have this resolved I'll move it back into its own file.
fixedState is updating with each submit; fixed.map(asset => console.log(asset)) works just fine.
Why does updating the state not re-render the table?
Thanks
Use spread syntax to clone the
fixedState
array so you do not reference and mutate the original array. To do this, changeconst assets = fixedState;
toconst assets = [...fixedState];
Below I just assigned
asset.title
to all the tds, I imagine this just placeholder data