Reactjs Redux Store fetch需要很长时间,会弄乱使用条件渲染的react组件,需要更快的数据

Reactjs Redux Store fetch需要很长时间,会弄乱使用条件渲染的react组件,需要更快的数据,reactjs,d3.js,redux,Reactjs,D3.js,Redux,编辑:我不知道如何缩短这篇文章。。。我不希望它太长,我发布的很多代码都是注释/或者可以快速浏览(前几个代码块),直到你进入渲染 Edit2:我在看react的文档,看看我是否遗漏了一些明显的东西。我可能 我正在努力在react中创建组件的条件呈现(其中一个组件取决于其他组件的值),然后使用这些组件创建D3图。这是我的第一个react应用程序,将react与从redux商店获取数据、创建条件组件以及同时使用D3结合起来一直是一个挑战。考虑到我遇到的困难,我担心我没有以正确的“反应”方式做某些事情。

编辑:我不知道如何缩短这篇文章。。。我不希望它太长,我发布的很多代码都是注释/或者可以快速浏览(前几个代码块),直到你进入渲染

Edit2:我在看react的文档,看看我是否遗漏了一些明显的东西。我可能

我正在努力在react中创建组件的条件呈现(其中一个组件取决于其他组件的值),然后使用这些组件创建D3图。这是我的第一个react应用程序,将react与从redux商店获取数据、创建条件组件以及同时使用D3结合起来一直是一个挑战。考虑到我遇到的困难,我担心我没有以正确的“反应”方式做某些事情。我的抓取花费了很长时间,这一事实也没有帮助,因为代码正在呈现需要这些抓取数据的数据,破坏了我的D3图形

以下是我目前掌握的情况:

my ByPitchKZonesApp组件中的所有导入

// Fairly certain I've got all of this imported correctly 

// Import React Components
import React, {Component} from 'react';
import { connect } from 'react-redux';

// Import Headers / Buttons / Select / D3 Components
import ToolButtonGroup from '../../components/AppButtons/ToolButtonGroup'; 
import Select from 'react-select';
import 'react-select/dist/react-select.css';
import D3ByPitchKZones from '../../components/D3ByPitchKZones';

// Import Actions (to get data)
import { fetchMlbIdsLogosColors } from '../../actions/mlb-ids-logos-colors-action';
import { fetchMlbStatcastSavantAll } from '../../actions/mlb-statcast-savant-all-action';

// Import CSS for this App
import './ByPitchKZonesApp.css'
    const pitchOrHitButtonGroup = {
        borderRadius: "25px",
        margin: "2%",
        padding: "10%",
        fontsize: "2em",
        border: "2px solid #BBB",
        gridColumns: 2, minRowHeight: "130px", 
        header: "",         
        buttons: [
            { value: "Pitchers", label: "Pitchers" },
            { value: "Hitters", label: "Hitters" },
        ]}
初始化组件

// My app has 2 states: 
  // pitchersOrHitters is set using the ToolButtonGroup on the page
  // selectedPlayer is  set using the Select Input
    // The values in the Select Input dropdown are conditional on the value of pitchersOrHitters

class ByPitchKZonesApp extends Component {

    constructor(props){
        super(props);
        this.state = {
            pitchersOrHitters: "Pitchers",
            selectedPlayer: ""
        }
    }
        return(
            <div className="pageContainer">
                <div className="hitOrPitchButtonsContainer">
                    <ToolButtonGroup
                        params={pitchOrHitButtonGroup}
                        value={this.state.pitchersOrHitters}
                        handler={this.handlePitchHitChange} />
                </div>
                {playerSelect}
                <div className="d3Container">
                    <D3ByPitchKZones
                        id={'d3-scatter'}
                        height={window.innerWidth*0.425}
                        width={window.innerWidth*0.85}
                        padding={50}
                        margin={{top:30, right:20, bottom:20, left:20}}
                        pitchfxData={pitchfxData}
                        theseGames="entireSeason"
                        pitcherOrHitter={this.state.pitcherOrHitter}
                        playerName={this.state.selectedPlayer && this.state.selectedPlayer.label} />
                </div>
            </div>
        )
    }
}
从redux存储获取数据

// fetchMlbStatcastSavantAll() returns a large object pitchfxData, however this is taking 10-20 seconds, which is giving me issues with the rendering
componentDidMount(){
    this.props.fetchMlbIdsLogosColors();
    this.props.fetchMlbStatcastSavantAll();
}
按钮并选择处理程序

// I believe I have this setup correctly

// Button and Select Handlers!
handlePitchHitChange = (pitchersOrHitters) => {
    this.setState({pitchersOrHitters})
}

handlePlayerChange = (selectedPlayer) => {
    this.setState({ selectedPlayer: selectedPlayer });
}
渲染

render() {

    // since pitchfxData is taking so long to load, check here if the load has been completed yet
    const dataLoaded = (this.props.pitchfxData) ? "true" : false;
    const { pitchersOrHitters } = this.state;
    const { pitchfxData } = this.props;


    // Cannot render the select widget until the pitchfxData loads
    // playerSelect is the conditional component here - depends on data from the buttons
    if(dataLoaded) {

        // Values in the select widget are conditional on the button clicked, whether its Pitchers or Hitters
        if(pitchersOrHitters == "Pitchers") {
            var name_col = "pitcher_name"
        } else {
            var name_col = "batter_name"
        }

        var players = [... new Set(pitchfxData.map(pitch => pitch[name_col]))]
            .map(player => {
                return {value: player, label: player}
            });

        var playerSelect = <div className="playerSelectContainer">                      
                <Select
                    name="team-select"
                    clearable={true}
                    searchable={true}
                    onChange={this.handlePlayerChange} 
                    value={this.state.selectedPlayer} 
                    options={players} />
            </div>  
    } else {
        // load a blank div in place of the select widget if data hasnt loaded yet
        var playerSelect = <div className="playerSelectContainer"></div>
    }
返回组件

// My app has 2 states: 
  // pitchersOrHitters is set using the ToolButtonGroup on the page
  // selectedPlayer is  set using the Select Input
    // The values in the Select Input dropdown are conditional on the value of pitchersOrHitters

class ByPitchKZonesApp extends Component {

    constructor(props){
        super(props);
        this.state = {
            pitchersOrHitters: "Pitchers",
            selectedPlayer: ""
        }
    }
        return(
            <div className="pageContainer">
                <div className="hitOrPitchButtonsContainer">
                    <ToolButtonGroup
                        params={pitchOrHitButtonGroup}
                        value={this.state.pitchersOrHitters}
                        handler={this.handlePitchHitChange} />
                </div>
                {playerSelect}
                <div className="d3Container">
                    <D3ByPitchKZones
                        id={'d3-scatter'}
                        height={window.innerWidth*0.425}
                        width={window.innerWidth*0.85}
                        padding={50}
                        margin={{top:30, right:20, bottom:20, left:20}}
                        pitchfxData={pitchfxData}
                        theseGames="entireSeason"
                        pitcherOrHitter={this.state.pitcherOrHitter}
                        playerName={this.state.selectedPlayer && this.state.selectedPlayer.label} />
                </div>
            </div>
        )
    }
}
话虽如此,我的问题是:

(1) 我是否在渲染函数中有条件地正确渲染选择输入?我正在检查按钮值是什么,并根据来自按钮的投手或击球手的值以不同方式呈现选择小部件{playerSelect}。我将不得不添加额外的条件按钮组组件,这些组件基于这个pitchersOrHitters状态变量,并希望正确地执行此操作。。。如果render()中不是if-else,那么是什么

(2) 我的应用程序正在崩溃,因为需要pitchfxData的D3组件在加载pitchfxData之前(在此.props.fetchMlbStatcastSavantAll()完成获取pitchfxData之前)正在渲染。这是一个问题,我不知道如何(a)更快地加载pitchfxData或(b)告诉D3组件在渲染之前等待数据加载


谢谢

有几种不同的方法来处理条件呈现JSX。通常,在呈现和返回之间的内容会放在一个函数中,然后在JSX中调用该函数

为了防止D3组件提前渲染,您可以检查道具是否存在,您可以在return或单独的函数(如我的“selectPlayers”函数)中执行

我的例子有很多方法可以浓缩和改写,但我认为这是一个好的开始

playerSelect = () => {
  const { pitchersOrHitters } = this.state
  const { pitchfxData } = this.props
  let name_col
  if (pitchersOrHitters == 'Pitchers') {
    name_col = 'pitcher_name'
  } else {
    name_col = 'batter_name'
  }

  const players = [...new Set(pitchfxData.map(pitch => pitch[name_col]))].map(player => {
    return { value: player, label: player }
  })

  var playerSelect = (
    <div className='playerSelectContainer'>
      <Select
        name='team-select'
        clearable
        searchable
        onChange={this.handlePlayerChange}
        value={this.state.selectedPlayer}
        options={players}
            />
    </div>
    )
    return playerSelect
}

render() {
       return(
            <div className="pageContainer">
                <div className="hitOrPitchButtonsContainer">
                    <ToolButtonGroup
                        params={pitchOrHitButtonGroup}
                        value={this.state.pitchersOrHitters}
                        handler={this.handlePitchHitChange} />
                </div>
                //check if props have loaded to conditionally render JSX
                {this.props.pitchfxData ? 
                    this.playerSelect()
                    : <div className="playerSelectContainer"></div>
                }
                //again checking if the props have loaded and if not then nothing with be rendered in place of the D3 component
                {
                this.props.pitchfxData ? 
                <div className="d3Container">
                    <D3ByPitchKZones
                        id={'d3-scatter'}
                        height={window.innerWidth*0.425}
                        width={window.innerWidth*0.85}
                        padding={50}
                        margin={{top:30, right:20, bottom:20, left:20}}
                        pitchfxData={pitchfxData}
                        theseGames="entireSeason"
                        pitcherOrHitter={this.state.pitcherOrHitter}
                        playerName={this.state.selectedPlayer && this.state.selectedPlayer.label} />
                </div>
                : 
                undefined
                }
            </div>
        )
    }
playerSelect=()=>{
const{pitchersOrHitters}=this.state
const{pitchfxData}=this.props
让我给你的名字命名
如果(投手或击球手==‘投手’){
name\u col='pitcher\u name'
}否则{
name\u col='batter\u name'
}
constplayers=[…新设置(pitchfxData.map(pitch=>pitch[name\u col]))].map(player=>{
返回{value:player,label:player}
})
变量playerSelect=(
)
返回玩家选择
}
render(){
返回(
//检查是否已加载道具以有条件地呈现JSX
{this.props.pitchfxData?
这个.playerSelect()
: 
}
//再次检查道具是否已加载,如果未加载,则将不显示任何内容来代替D3组件
{
这个.props.pitchfxData?
: 
未定义
}
)
}