简体   繁体   中英

Component duplicates when dispatching an action via redux

So I have written some code to display a chart and I have also written a function which will allow me to change the timeframe of the chart. However, when this function is invoked, a duplicate chart pops up.

Here is the Chart.js

let chartProperties = {
    width: 1000,
    height: 500,
    timeScale: {
        timeVisible: true,
        secondsVisible: false
    }
}

const Chart = (props) => {

    useEffect(() => {
        fetchData()
    }, [])

    const lightweightChart = createChart(document.body, chartProperties);
    const candleSeries = lightweightChart.addCandlestickSeries();

    const fetchData = () => {
        axios.get(`https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1m&limit=1000`)
            .then(response => response.data)
            .then(data => {
                const candlestickData = data.map(d => {
                    return { time: d[0] / 1000, open: parseFloat(d[1]), high: parseFloat(d[2]), low: parseFloat(d[3]), close: parseFloat(d[4]) }
                });
                candleSeries.setData(candlestickData);
            }).catch(error => console.log(error))
    }

    return (
        <div>
        </div>
    );
}

const mapStateToProps = (state) => {
    return {
        chartData: state.chartOptionsReducer
    }
}

export default connect(mapStateToProps)(Chart);

Here is the action creator chartActions.js

export const changeTimeframe = (timeframe) => {
    return {
        type: 'CHANGE_TIMEFRAME',
        payload: {
            timeframe: timeframe
        }
    }
}

Here is the reducer chartOptionsReducer.js

const initState = {
    symbol: 'BTCUSDT',
    timeframe: '4h'
}

const chartOptionsReducer = (state = initState, action) => {
    console.log(action)
    if (action.type === 'CHANGE_TIMEFRAME') {
        let newTimeframe = action.payload.timeframe
        return {
            ...state,
            timeframe: newTimeframe
        }
    } else {
        return state;
    }
}

export default chartOptionsReducer;

And finally this is where the action gets called from OptionsColumn.js

const OptionColumn = (props) => {

    const handleTimeframe = (timeframe) => {
        props.changeTimeframe(timeframe)
    }

    return (
        <Menu
            label="Timeframe"
            items={[
                { label: '1m', onClick: () => { handleTimeframe('1m') } },
                { label: '4h', onClick: () => { handleTimeframe('4h') } },
            ]}
        />
    )
}

const mapDispatchToProps = (dispatch) => {
    return {
        changeTimeframe: (timeframe) => { dispatch(changeTimeframe(timeframe)) }
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(OptionColumn);

I think the issue may be coming from this line in Chart.js though i'm not sure, and i'm also not sure how to avoid it:

const lightweightChart = createChart(document.body, chartProperties);

BONUS ISSUE: Anybody who is familiar with the lightweightChart package, is there a way to display the chart within a container instead of document.body? Thanks

In React, the component will re-render under certain conditions which include props changes.

This code bellow will re-run whenever the Chart.js re-render (which it will create new chart targeting document.body every time)

const lightweightChart = createChart(document.body, chartProperties);

Put it in your useEffect with your fetchData() call

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM