Как повторно отображать каждый раз, когда состояние изменяется с лимитом вызовов API? - PullRequest
1 голос
/ 29 мая 2020

Редактировать: Люди из БУДУЩЕГО: посмотрите это видео -

https://www.youtube.com/watch?v=FyxFSkh2wug и статью, предоставленную Леонардо.

У меня есть компонент панели поиска и диаграмма запасов. компонент, которые являются дочерними по отношению к родительскому компоненту. Я хочу повторно отображать биржевую диаграмму каждый раз, когда вводится ключ в строке поиска. Я новичок в реакции, поэтому, пожалуйста, не забывайте мой код.

Я пробовал использовать shouldComponentUpdate, и он сделал слишком много вызовов API. В функции CorrectRender я пытался вернуть StockChart каждый раз при изменении тикера, но это не сработало.

Я изо всех сил старался описать методы, которые я написал, пожалуйста, не стесняйтесь задавать любые вопросы.

Это родительский компонент, я вызываю его внутри приложения. js

import React, { Component } from 'react'
import StockChart from './StockChart';
import SearchBar from './SearchBar';


// Renders stockChart when value is entered
// I tried to re-render by using a current and previousTicker symbols but it didn't work.

function CorrectRender(props, oldtick) {
    const ticker = props.props;
    console.log("props", props)
    const previousTicker = props.oldtick;
    if (ticker.length > 0 && previousTicker !== ticker) {
        return <div>
            <p>{ticker}</p>
            <StockChart stockSymbol = {ticker} previousTicker={previousTicker}/>
        </div>
    }
    return null;
    }

export class Parent extends Component {
    constructor(props) {
        super(props);
        this.state = {
            stockSymbol: '',
            previousTicker: ''
        }
        this.callbackFunction = this.callbackFunction.bind(this);
    }


    shaveData(value) {
        let value1 = value.split(`,`);
        value = value1[0];
        this.setState({
            stockSymbol: value,
        });
    }



    callbackFunction(sS)  {
        this.setState({ previousTicker: this.state.stockSymbol});
        this.shaveData(sS);
    };

    render() {
        return (
            <div>
                <SearchBar parentCallback = {this.callbackFunction}/>
                <CorrectRender props={this.state.stockSymbol} oldtick={this.state.previousTicker}/>
            </div>
        )
    }
}

export default Parent;

Это компонент SEARCHBAR.

import React, { Component } from 'react';
import './SearchBar.css';



export class SearchBar extends Component {
    constructor(props) {
        super(props);
        this.state = {
            search: ' ',
            tickerList: [],
        }
    }



    // Get a list of tickers from an API, this is not the api call that is being overused
    // I want the data to show to the user as "Ticker, Company name" which is what the second (.then) is doing
    fetchTickers(stockSymbol) {
        const pointer = this;
        let arr = [];
        console.log(stockSymbol);
        let url = `https://ticker-2e1ica8b9.now.sh/keyword/${stockSymbol}`;

        fetch(url) 
            .then( function(response) {
                return response.json();
            })
            .then ( function(data) {
                for (var key in data) {
                    arr.push(data[key]['symbol'] + ", "+ data[key]['name'])
                };

                pointer.setState({
                    tickerList: arr
                })
            }

            )
    }

    // this is for handling keys in the search bar and rendering new results based on the 
    critera
    textChange = (e) => {
        const value = e.target.value;
        let arr = [];
        if (value.length > 0) {
            const regex = new RegExp(`^${value}`, 'i');
            this.fetchTickers(value);
            arr = this.state.tickerList.sort().filter(tick => regex.test(tick));
        }
        this.setState({
            tickerList: arr,
            search: value
        });
    }


    // This will be called when an option is chosen by user
    tickerChosen(value) {
        let value1 = value.split(`,`);
        value = value1[0];
        this.setState({
            search: value,
            tickerList: []
        });



    };


    // list of suggestions on user side based on criteria
    tickerSuggestions () {
        const { tickerList } = this.state;
        if (tickerList.length === 0) {
            return null;
        }
        return (
            <ul>
                {tickerList.map((ticker) => <li key={ticker} onClick={() =>  {this.props.parentCallback(ticker); this.tickerChosen(ticker);} }>{ticker}</li>)}
            </ul>
        )
    };



    render() {
        const { search } = this.state;
        return (
            <div className= 'SearchBar'>
                <input value = { search } onChange={this.textChange} type='text' />
                {this.tickerSuggestions()}

            </div>
        )
    }
}

export default SearchBar

Это компонент StockChart.

import React, { Component } from 'react';
import Plot from 'react-plotly.js';


class StockChart extends Component {
    constructor(props) {
        super(props);
        this.state = {
            stockXValues: [],
            stockYValues: [],
            stockSymbol: '',

        }
}

componentDidMount() {
    this.fetchStock();
}

fetchStock() {
    const pointer = this;
    const symbol = this.props.stockSymbol;

    const API_KEY = `X`;
    let API_Call = `https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=${symbol}&outputsize=compact&apikey=${API_KEY}`;

    let StockXValuesFunc = [];
    let StockYValuesFunc = [];



    fetch(API_Call)
        .then(
            function(response) {
                return response.json();
            }
        )
        .then(
            function(data) {
                console.log(data);

                for (var key in data['Time Series (Daily)']) {
                    StockXValuesFunc.push(key);
                    StockYValuesFunc.push(data['Time Series (Daily)']
                    [key]['4. close']);
                }
                pointer.setState({
                    stockXValues: StockXValuesFunc,
                    stockYValues: StockYValuesFunc,
                });


            }
        )

}
render() {
  return (
    <div>
        <h2>{this.props.stockSymbol}</h2>
        <Plot
            data={[
            {
                x: this.state.stockXValues,
                y: this.state.stockYValues,
                type: 'scatter',
                mode: 'lines+markers',
                marker: {color: 'red'},
            },
            ]}
            layout={ {width: 720, height: 440, title: 'Closing Price over the last 100 days'} }
        />
    </div>
  )
 }
}

Экспорт StockChart по умолчанию;

Ответы [ 2 ]

1 голос
/ 29 мая 2020

Здесь вы можете найти хорошее объяснение того, как дросселировать и избегать выполнения стольких вызовов API: Повысьте производительность вашего реагирующего приложения, используя дросселирование и устранение ошибок

0 голосов
/ 29 мая 2020

То, что вы ищете, - это Регулирование или Debouncing

Регулирование выполняет заданную функцию по истечении заданного времени.

Debouncing предписывает, что функция не будет вызываться снова, пока не пройдет определенное время с момента ее последнего вызова. При противодействии он игнорирует все вызовы функции и ожидает, пока функция не перестанет вызываться в течение определенного времени. или rx js.

Пример регулирования

    // ...
import { throttle } from lodash;
class autocomp extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            results: []
        }
       this.handleInputThrottled = throttle(this.handleInput, 100)
    }
    handleInput = evt => {
        const value = evt.target.value
        const filteredRes = data.filter((item)=> {
            // algorithm to search through the `data` array
        })
        this.setState({ results: filteredRes })
    }
    render() {
        let { results } = this.state;
        return (
            <div className='autocomp_wrapper'>
                <input placeholder="Enter your search.." onChange={this.handleInputThrottled} />
                <div>
                    {results.map(result=>{result})}
                </div>
            </div>
        );
    }
}

Пример подавления

    // ...
import { debounce } from 'lodash';
class autocomp extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            results: []
        }
       this.handleInputThrottled = debounce(this.handleInput, 100)
    }
    handleInput = evt => {
        const value = evt.target.value
        const filteredRes = data.filter((item)=> {
            // algorithm to search through the `data` array
        })
        this.setState({ results: filteredRes })
    }
    render() {
        let { results } = this.state;
        return (
            <div className='autocomp_wrapper'>
                <input placeholder="Enter your search.." onChange={this.handleInputThrottled} />
                <div>
                    {results.map(result=>{result})}
                </div>
            </div>
        );
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...