当状态更新时,组件不会重新渲染更新状态(REACT)

时间:2021-06-04 16:35:41

标签: javascript reactjs state

好吧,让我开始吧,这段代码可能看起来很乱,但我认为问题很简单。

因此,每当我更改以下“TitleCards”子组件的父级中的状态时,子组件中的状态也会发生变化,但“TitleCards”组件的渲染方法中的组合总价值不会根据更改重新计算状态。我认为这与 async 函数有关,但我不确定。

有什么想法吗?我想要的只是当子组件中的状态发生变化时(我可以使用开发工具看到它正在发生变化),让组件自动重新渲染/重新计算带有更改状态的组合总和。

import "./StockCard.css";
import { IEX } from "./IEX.js";
import moment from 'moment';
import Folder from "./folder.png";
import MoneyBag from "./money-bag.png";
import Handshake from "./hand-shake.png";
import add from "./add.png";
import NumberFormat from 'react-number-format';

const LOGO_API = "https://eodhistoricaldata.com/img/logos/US/";

class TitleCards extends Component {
    constructor(props){
        super(props)
        this.arr = this.totalPortfolio();
        this.state ={
            portfolioTotal: '',
            WhenThisChangesShouldntTheComponentReRender: this.props.info,
        }
        this.totalPortfolio = this.totalPortfolio.bind(this);
        this.getIntradayPrice = this.getIntradayPrice.bind(this);

    }

    static defaultProps = {
        TitleCardInfo: [
          { name: "Portfolio", ticker: "DIA"}, 
          { name: "Total Return", ticker: "SPY"}, 
          { name: "Positions Held", ticker: "IWM"}, 
          { name: "Add Position", ticker: "Gold"},],
      }

    async getIntradayPrice(tick) {
        const resp = await fetch(`${IEX.base_url}/stock/${tick}/intraday-prices?chartLast=1&token=${IEX.api_token}`);
        return resp.json();
      }

    async totalPortfolio() {
        const { info } = this.props;
        const respPromises = info.map(({ tick }) => this.getIntradayPrice(tick));
        const respArrays = await Promise.all(respPromises);
        const result = respArrays.reduce((acc, val, index) => acc + val[0].close * info[index].amtPurch, 0);
        return result;
      }
      
    componentDidMount() {
        this.totalPortfolio()
          .then(portfolioTotal => {
            this.setState({
              portfolioTotal
            });
          })
        .catch(error => {
            // add any required error handling/messaging here
        });
    }

    render(){  
        const { portfolioTotal } = this.state;
        return(
            <div className="positioning">
                <div className="StockCardTitle">
                    <img src={Folder} className="StockCardTitle-image" />  
                    {portfolioTotal}
                </div>
            </div>
        )
    }
}
export default TitleCards;

状态发生变化并传递给 TitleCard 组件的父组件(如果有帮助的话)。

import React, { Component } from 'react';
import StockCard from "./StockCard";
import TitleCards from "./TitleCards";
import { IEX } from "./IEX.js";

const LOGO_API = "https://eodhistoricaldata.com/img/logos/US/";

class UserInput extends Component {
    constructor(props){
        super(props)
        this.state ={
            tickerName: "",
            sAmtPurch: "",
            sPurchPrice: "",
            sDatePurch: "",
            tickerList: [
                { tick: "AAPL", amtPurch: 50, purchPrice: 10, datePurch: "01/01/2021"},
                { tick: "GOOG", amtPurch: "40", purchPrice: "10", datePurch: "01/01/2021"},
                { tick: "TSLA", amtPurch: "40", purchPrice: "10", datePurch: "01/01/2021"},
                { tick: "J", amtPurch: "40", purchPrice: "10", datePurch: "01/01/2021"},
                { tick: "AMZN", amtPurch: "40", purchPrice: "10", datePurch: "01/01/2021"},
                { tick: "FB", amtPurch: "40", purchPrice: "10", datePurch: "01/01/2021"},
                { tick: "BABA", amtPurch: "40", purchPrice: "10", datePurch: "01/01/2021"},
                { tick: "JNJ", amtPurch: "40", purchPrice: "10", datePurch: "01/01/2021"},
                { tick: "JPM", amtPurch: "40", purchPrice: "10", datePurch: "01/01/2021"},
                { tick: "XOM", amtPurch: "30", purchPrice: "10", datePurch: "01/01/2021"},
                ],
            data4: {}
        }
        this.handler = this.handler.bind(this)
    }

    handleSubmit = (event) => {
        event.preventDefault()
        // Initialize state into variables 
        const tickerToBeAdded = { tick: this.state.tickerName, amtPurch: this.state.sAmtPurch, purchPrice: this.state.sPurchPrice, datePurch: this.state.sDatePurch};
        const tickerList = this.state.tickerList;
        
        // Apend tickerList with inputed ticker
        const length = tickerList.length;
        tickerList[length] = tickerToBeAdded;
        this.setState({
            tickerList: tickerList
        })
    }
    handleInputChange = (event) => {
        event.preventDefault()
        // Store Input in State
        this.setState({
            [event.target.name]: event.target.value
        })
    }

    componentDidMount() {
    // query the api
    const url4 = `${IEX.base_url}/stock/${this.state.tickerList.tick}/intraday-prices?chartLast=1&token=${IEX.api_token}`;
    fetch(url4)
      .then((response) => response.json())
      .then((data4) => {
        this.setState({
          data4: data4[data4.length - 1],
        });
      });
    }

    render () {

        return (
            <div>
                <form onSubmit={this.handleSubmit}>
                    <p><input type='text' placeholder='Stock Ticker' name='tickerName' onChange={this.handleInputChange}/></p>
                    <p><input type='text' placeholder='Shares' name='sAmtPurch' onChange={this.handleInputChange}/></p>
                    <p><input type='text' placeholder='Purchase Price' name='sPurchPrice' onChange={this.handleInputChange}/></p>
                    <p><button>Send Message</button></p>
                </form>

                <div className="Charts">
                        <TitleCards info={this.state.tickerList}/>
                </div>
            </div>
        )
    }
}

export default UserInput;

1 个答案:

答案 0 :(得分:1)

componentDidMount 每个坐骑只触发一次。如果你想在每次组件重新渲染时运行一些东西,你需要 componentDidUpdate。看看这个 lifecycle diagram 使用什么方法。

componentDidUpdatethis.setState 一起使用时要小心。如果你在 componentDidUpdate 的每个周期盲目更新状态,你将触发一个无限循环。 (有关详细信息,请参阅 this answer。)