编辑:我不确定如何缩短这篇文章...我不想让它太长,我发布的很多代码都是评论/或者可以只是略读快速完成(前几个代码块)直到你进入渲染...
Edit2:我正在阅读这篇文章的反应文档 - https://reactjs.org/docs/conditional-rendering.html - 看看我是否错过了一些明显的东西。我可能有...
我正在努力创建反应中的组件的条件渲染(其中一个组件依赖于来自其他组件的值),然后用于创建D3图。这是我的第一个反应应用程序,并且与从redux商店获取数据做出反应,通过创建条件组件,使用D3一起使用,一直是一个挑战。我担心我没有做出正确反应的某些事情。时尚,考虑到我遇到的困难。我的提取花费很长时间的事实也没有帮助,因为代码渲染需要来自这些提取的数据,打破了我的D3图...
这是我到目前为止所拥有的:
我的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'
初始化组件
// 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: ""
}
}
从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>
}
道具传递给按钮组
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" },
]}
返回组件
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状态转换为此组件的道具
function mapStateToProps(reduxState) {
return {
colorLogoPalette: reduxState.mlbIdsLogosColorsReducer.mlbIdsLogosColorsData,
pitchfxData: reduxState.mlbStatcastSavantAllReducer.mlbStatcastSavantAllData
}
}
export default connect(mapStateToProps, { fetchMlbIdsLogosColors, fetchMlbStatcastSavantAll })(ByPitchKZonesApp);*
话虽如此,我的问题是:
(1)我是否有条件地在渲染函数中正确渲染选择输入?我正在检查按钮值是什么,并根据来自按钮的pitchersOrHitters的值以不同方式呈现Select Widget {playerSelect}。我将不得不添加基于此pitchersOrHitters状态变量的其他条件按钮组组件,并且想要正确执行此操作...如果不是render()中的if else,那么是什么?
(2)我的应用程序崩溃,因为D3组件(需要pitchfxData)在加载pitchfxData之前呈现(在this.props.fetchMlbStatcastSavantAll()完成获取pitchfxData之前)。这是一个问题,我不知道如何(a)更快地加载pitchfxData或(b)告诉D3组件在渲染之前等待数据加载......
谢谢!
答案 0 :(得分:1)
有几种不同的方法来处理有条件渲染JSX。通常,渲染和返回之间的内容将放在一个函数中,然后在JSX中调用该函数。
为防止D3组件提前渲染,您可以检查道具是否存在,您可以在返回时或在单独的函数中执行,例如我的&#34; selectPlayers&#34;功能。
有些方法可以压缩和重写我的例子,但我认为这是一个好的开始。
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>
)
}