当在另一个组件中更新上下文时,如何通过useContext触发一个组件的重新渲染

问题描述

我正在尝试使用API​​的响应来更新表。响应来自一个组件,而表位于另一个组件。我可以看到我已经成功更新了组件中的上下文,但是它似乎没有传递给其他组件。我尝试过更新上下文,然后通过道具钻探传递它,但这也不起作用。如何获取包含表的组件以侦听上下文中的更改?我组件的代码如下:

其中更新了上下文的组件:

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,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的传入响应作为道具传递给组件。在子组件中,您可以像这样使用useEffect

  useEffect(() => {
       code here or change states,whichever you need to do
        })

    },[props.responseIncomingFromParent])

让我知道这是否可行...

,

另一个问题给出的答案是,我需要将上下文变量扩展为另一个常量,然后使用该常量。

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:sql_demo/models/product.dart';

class DbHelper {
  //Creates a singleton class (it only creates once)
  static final DbHelper _singleton = DbHelper._internal();
  factory DbHelper() => _singleton;
  DbHelper._internal();

  //Creating an object of type database
  static Database _database;

  //Initializing or creating the database named mydb.db
  //Creating a products table with necessary fields
  Future<Database> initDatabase() async {
    //If this class was never instaciated,we will execute this method,otherwise return
    if (_database != null) return _database;
    String path = join(await getDatabasesPath(),'mydb.db');
    _database = await openDatabase(
      path,version: 1,onCreate: (Database db,int v) async {
        await db.execute(
            'CREATE TABLE Products (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,description TEXT,price REAL)');
      },);
    return _database;
  }

  //Select all products
  Future<List> getProducts() async {
    Database db = await initDatabase();
    return await db.query('Products');
  }

  //Create new product
  Future<int> createProduct(Product product) async {
    Database db = await initDatabase();
    print('Product added');
    return await db.insert(
      'Products',product.toMap(),);
  }

  //Update product
  Future<int> updateProduct(Product product) async {
    Database db = await initDatabase();
    return await db.update(
      'Products',where: 'id=?',whereArgs: [product.id],);
  }

  //Delete a product
  Future<int> deleteProduct(int productID) async {
    Database db = await initDatabase();
    return await db.delete('Products',whereArgs: [productID]);
  }
}