当所述上下文在另一个组件中更新时如何通过 useContext 在组件中触发重新渲染
How to trigger a re-render in a component via useContext when said context is updated in another component
我正在尝试使用 API 的响应更新 table。响应来自一个组件,而 table 位于另一个组件中。我可以看到我正在成功更新组件中的上下文,但它似乎没有传递给其他组件。我试过更新上下文,然后通过道具钻孔传递它,但这也没有用。如何让包含 table 的组件监听上下文的变化?我的组件的代码如下:
更新上下文的组件:
import React, { useState, useContext } from 'react';
import { Card } from 'react-bootstrap';
import axios from 'axios';
import Cd from './types/Cd';
import Bond from './types/Bond';
import AssetContext from '../../context/AssetContext';
const fixedCard = (props) => {
const [fixed, setFixed] = useContext(AssetContext);
const [bond, setBond] = useState(false);
const assets = fixed;
const getResult = (event) => {
const form = event.currentTarget;
event.preventDefault();
event.stopPropagation();
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,
length: iLength,
compoundFrequency: compound
}
axios.post("http://localhost:8080/compound-calculator/savings", body, { headers })
.then(res => {
assets.push(res.data);
setFixed(assets);
fixed.map(asset => console.log(asset));
});
}
}
const linkCursor = { cursor: 'pointer' }
const toggleBond = () => {
setBond(true);
}
const toggleCert = () => {
setBond(false);
}
return (
<Card body>
<Card.Title>
Compount interest calculator
</Card.Title>
<Card.Link onClick={() => toggleCert()} style={linkCursor}>Certificate</Card.Link>
<Card.Link onClick={() => toggleBond()} style={linkCursor}>Bond</Card.Link>
<hr></hr>
<br></br>
{!bond && <Cd getResult={getResult} />}
{bond && <Bond getResult={getResult} />}
<br></br>
</Card>
);
}
export default React.memo(fixedCard);
根组件:
import React, { useState, useEffect } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import './GrowthCalculator.css';
import { Container, CardDeck } from 'react-bootstrap';
import FixedCard from '../components/fixedAssets/FixedCard';
import StockCard from '../components/StockCard';
import ResultCard from '../components/ResultCard';
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];
return (
<main>
<AssetContext.Provider value={[...assets]}>
<Container>
<br></br>
<Navigation />
</Container>
<br></br>
<CardDeck>
<FixedCard /> //context updated here
<StockCard />
<ResultCard /> //trying to pass it here
</CardDeck>
<br></br>
<HowTo />
</AssetContext.Provider>
</main>
);
}
export default React.memo(growthCalculator);
我正在尝试将其传递给的组件(此处的布局仍在进行中):
import React, { useContext, useState } from 'react';
import { Card, Row, Col, Table } from 'react-bootstrap';
import AssetContext from '../context/AssetContext';
const resultCard = (props) => {
// eslint-disable-next-line
const [fixed, setFixed, stocks, setStocks] = useContext(AssetContext);
return (
<Card body>
<Card.Title>
Result card
</Card.Title>
<br></br>
<hr></hr>
<br></br>
<section>
<Row>
<Col>
<Table striped borderless hover size="sm" variant="secondary" responsive>
<thead>
<tr>
<th>
Compounding assets
</th>
</tr>
</thead>
<tbody>
//This doesn't render anything when fixed is updated in FixedCard.js
{fixed.map(asset => (
<tr>
<td>
${asset.principle}
</td>
<td>
total: ${asset.endValue}
</td>
</tr>))
}
</tbody>
</Table>
</Col>
<Col>
<Table striped borderless hover size="sm" variant="secondary" responsive>
<thead>
<tr>
<th>
Stocks
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Ticker
</td>
<td>
Fair price
</td>
<td>
Discount price
</td>
</tr>
</tbody>
</Table>
</Col>
</Row>
</section>
</Card>
);
}
export default resultCard;
重申一下我的问题,如何让 resultCard 监听 AssetContext 中的变化?
谢谢
为了聆听变化然后实施变化,我所做的是使用 useEffect,我必须聆听变化并进行更改。例如,您可以将来自 api 的传入响应作为 props 传递给组件。在子组件中,您可以像这样使用 useEffect
useEffect(() => {
code here or change states, whichever you need to do
})
}, [props.responseIncomingFromParent])
让我知道这是否有效...
在另一个问题中给出的答案是我需要将上下文变量传播到另一个常量中,然后使用那个。
const fixedArr = [...fixed];
/* the code above*/
fixedArr.map(asset => {
//the code you see above
}
);
我正在尝试使用 API 的响应更新 table。响应来自一个组件,而 table 位于另一个组件中。我可以看到我正在成功更新组件中的上下文,但它似乎没有传递给其他组件。我试过更新上下文,然后通过道具钻孔传递它,但这也没有用。如何让包含 table 的组件监听上下文的变化?我的组件的代码如下:
更新上下文的组件:
import React, { useState, useContext } from 'react';
import { Card } from 'react-bootstrap';
import axios from 'axios';
import Cd from './types/Cd';
import Bond from './types/Bond';
import AssetContext from '../../context/AssetContext';
const fixedCard = (props) => {
const [fixed, setFixed] = useContext(AssetContext);
const [bond, setBond] = useState(false);
const assets = fixed;
const getResult = (event) => {
const form = event.currentTarget;
event.preventDefault();
event.stopPropagation();
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,
length: iLength,
compoundFrequency: compound
}
axios.post("http://localhost:8080/compound-calculator/savings", body, { headers })
.then(res => {
assets.push(res.data);
setFixed(assets);
fixed.map(asset => console.log(asset));
});
}
}
const linkCursor = { cursor: 'pointer' }
const toggleBond = () => {
setBond(true);
}
const toggleCert = () => {
setBond(false);
}
return (
<Card body>
<Card.Title>
Compount interest calculator
</Card.Title>
<Card.Link onClick={() => toggleCert()} style={linkCursor}>Certificate</Card.Link>
<Card.Link onClick={() => toggleBond()} style={linkCursor}>Bond</Card.Link>
<hr></hr>
<br></br>
{!bond && <Cd getResult={getResult} />}
{bond && <Bond getResult={getResult} />}
<br></br>
</Card>
);
}
export default React.memo(fixedCard);
根组件:
import React, { useState, useEffect } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import './GrowthCalculator.css';
import { Container, CardDeck } from 'react-bootstrap';
import FixedCard from '../components/fixedAssets/FixedCard';
import StockCard from '../components/StockCard';
import ResultCard from '../components/ResultCard';
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];
return (
<main>
<AssetContext.Provider value={[...assets]}>
<Container>
<br></br>
<Navigation />
</Container>
<br></br>
<CardDeck>
<FixedCard /> //context updated here
<StockCard />
<ResultCard /> //trying to pass it here
</CardDeck>
<br></br>
<HowTo />
</AssetContext.Provider>
</main>
);
}
export default React.memo(growthCalculator);
我正在尝试将其传递给的组件(此处的布局仍在进行中):
import React, { useContext, useState } from 'react';
import { Card, Row, Col, Table } from 'react-bootstrap';
import AssetContext from '../context/AssetContext';
const resultCard = (props) => {
// eslint-disable-next-line
const [fixed, setFixed, stocks, setStocks] = useContext(AssetContext);
return (
<Card body>
<Card.Title>
Result card
</Card.Title>
<br></br>
<hr></hr>
<br></br>
<section>
<Row>
<Col>
<Table striped borderless hover size="sm" variant="secondary" responsive>
<thead>
<tr>
<th>
Compounding assets
</th>
</tr>
</thead>
<tbody>
//This doesn't render anything when fixed is updated in FixedCard.js
{fixed.map(asset => (
<tr>
<td>
${asset.principle}
</td>
<td>
total: ${asset.endValue}
</td>
</tr>))
}
</tbody>
</Table>
</Col>
<Col>
<Table striped borderless hover size="sm" variant="secondary" responsive>
<thead>
<tr>
<th>
Stocks
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Ticker
</td>
<td>
Fair price
</td>
<td>
Discount price
</td>
</tr>
</tbody>
</Table>
</Col>
</Row>
</section>
</Card>
);
}
export default resultCard;
重申一下我的问题,如何让 resultCard 监听 AssetContext 中的变化?
谢谢
为了聆听变化然后实施变化,我所做的是使用 useEffect,我必须聆听变化并进行更改。例如,您可以将来自 api 的传入响应作为 props 传递给组件。在子组件中,您可以像这样使用 useEffect
useEffect(() => {
code here or change states, whichever you need to do
})
}, [props.responseIncomingFromParent])
让我知道这是否有效...
在另一个问题中给出的答案是我需要将上下文变量传播到另一个常量中,然后使用那个。
const fixedArr = [...fixed];
/* the code above*/
fixedArr.map(asset => {
//the code you see above
}
);