我有一个布局组件(下面)。我通过this.props.children(或现在的childrenWithProps)注入此组件的两个组件有一个我为它们创建的日期范围组件,允许用户选择从teh api中提取的数据范围。一个是播放器仪表板,一个是团队仪表板(默认视图,显示在第二个代码块中)。当用户在团队仪表板上并搜索播放器并移动到该播放器仪表板时,我希望选择的日期范围(存储为this.state.startDate和this.state.EndDate)继续进入播放器仪表板,然后反之亦然。我觉得这是redux的一个很好的用例,但到目前为止,我已经设法通过传递道具和日期范围的redux实现似乎令人生畏。任何帮助将非常感激。此外,我有新的反应,知道我需要做大量的重新格式化。
import React, { PropTypes, Component } from 'react';
import '../../styles/core.scss';
import TopNav from 'components/top-nav';
import LeftNav from 'components/left-nav';
export default class CoreLayout extends Component {
static propTypes = {
children: PropTypes.element
};
constructor(props, context) {
super(props, context);
this.state = {
team: null,
teamPositions: []
};
}
activeTeam(team){
console.log(team);
this.setState({
team: team
}, () => {
return this.state;
});
}
componentWillMount() {
}
getTeamPositions(positions){
this.setState({
teamPositions: positions
}, () => {
return this.state;
});
}
render() {
var childrenWithProps = React.Children.map(this.props.children, (child) => React.cloneElement(child, { team: this.state.team, teamPositions: this.state.teamPositions }));
return (
<div className='page-container'>
<TopNav
onTeamChange={team => this.activeTeam(team)}
sendTeamPositions={positions => this.getTeamPositions(positions)}
/>
<LeftNav />
{( this.state.team !== null ) ?
<div className='view-container'>
{ childrenWithProps }
</div>
: null }
</div>
);
}
}
这是团队仪表板
import React, { PropTypes, Component } from 'react';
import { getDataRange, getTeams, getFile, getAllHitsData, getPlayers} from 'api/index.js';
import moment from 'moment';
import {Table, Thead, Th, Tr, Td} from 'components/Reactable';
import Autosuggest from 'react-autosuggest';
import { Link } from 'react-router';
import ScatterPlot from 'components/scatterplot';
import DashboardStats from 'components/dashboard-stats';
import DateRangeComponent from 'components/date-range';
import AdminSquare from 'components/admin-square';
let allHitDatas = [];
let hitDatas = [];
let teams = [];
let newFile = '';
let players = [];
export default class Dashboard extends Component {
static propTypes = {
team: PropTypes.object.isRequired
// teamPositions: PropTypes.array.isRequired
};
constructor(props, context) {
super(props, context);
this.state = {
showRangePicker: false,
hitDatas: [],
teams: [],
start: '',
end: '',
team: this.props.team,
selectedTeamID: null,
selectedTeamName: "",
newFileConfirmation: false,
players: [],
allHitDatas: [],
suggestions: this.getSuggestions(''),
startDate: moment().format('YYYY-MM-DD'),
endDate: moment().format('YYYY-MM-DD'),
selected: '',
showDatePickerControls: false,
showScatterPlot: true
};
this.onChange = this.onChange.bind(this);
this.onSuggestionsUpdateRequested = this.onSuggestionsUpdateRequested.bind(this);
}
onChange(event, { newValue }) {
this.setState({
value: newValue
});
}
onSuggestionsUpdateRequested({ value }) {
this.setState({
suggestions: this.getSuggestions(value)
});
}
formatDate(date) {
return moment(date).format('YYYY-MM-DD');
}
formatDisplayDate(date) {
return moment(date).format('MMMM DD, YYYY');
}
componentWillReceiveProps() {
this.setState({
team: this.props.team,
selectedTeamID: this.props.team.id
}, () => {
this.dataChangeHelper();
});
console.log(this.props);
}
componentWillMount() {
console.log(this.props);
let defaultStartDate = "03/01/15";
let defaultEndDate = "05/18/16";
const config = {
start: this.state.startDate || defaultStartDate,
end: this.state.endDate || defaultEndDate,
team: this.props.team.id
};
getAllHitsData(config)
.then((response) => {
allHitDatas = response.data;
this.setState({
allHitDatas: allHitDatas
}, () => {
return this.state;
});
});
getDataRange(config)
.then((response) => {
hitDatas = response.data;
this.setState({
hitDatas: hitDatas,
start: config.start,
end: config.end
});
});
getTeams().then((response) => {
teams = response.data;
this.setState({teams: teams});
});
getPlayers().then((response) => {
players = response.data;
this.setState({
players: players
}, () => {
return this.state;
});
});
}
getSuggestions(value) {
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
return inputLength === 0 ? [] : players.filter(player =>
(player.NameFirst.toLowerCase().slice(0, inputLength) === inputValue || player.NameLast.toLowerCase().slice(0, inputLength) === inputValue)
);
}
getSuggestionValue(suggestion) { // when suggestion selected, this function tells
return suggestion.NameFirst; // what should be the value of the input
}
renderSuggestion(suggestion) {
return (
<span><Link to={ "/view-player/" + suggestion.id }>{ suggestion.NameFirst + " " + suggestion.NameLast }</Link></span>
);
}
shouldRenderSuggestions(value) {
if (value) {
return value.trim().length > 0;
}
}
renderReactable(hitDatas) {
return hitDatas.map((hitData) => {
// console.log(hitData);
if (Number(hitData.playerTeamId) === Number(this.state.selectedTeamID) || this.state.selectedTeamID === null) {
return (
<Tr key={hitData.MaxHic}>
<Td column="name" data={hitData.playerNameLast + ', ' + hitData.playerNameFirst} />
<Td column="numHits" data={hitData.numHits} />
<Td column="maxHic" data={Math.round(hitData.MaxHic)} />
</Tr>
);
}
});
}
renderReactableTwo(allHitDatas) {
return allHitDatas.map((hitData) => {
// console.log(hitData);
if (Number(hitData.playerTeamId) === Number(this.state.selectedTeamID) || this.state.selectedTeamID === null) {
return (
<Tr key={hitData.Hic}>
<Td column="name" data={hitData.playerNameLast + ', ' + hitData.playerNameFirst} />
<Td column="hic" data={Math.round(hitData.Hic)} />
</Tr>
);
}
});
}
dataChangeHelper() {
console.log(this.props);
const newConfig = {
start: this.state.startDate,
end: this.state.endDate,
team: this.props.team.id
};
getDataRange(newConfig)
.then((response) => {
hitDatas = response.data;
this.setState({
hitDatas: hitDatas
});
});
getAllHitsData(newConfig)
.then((response) => {
console.log(response);
allHitDatas = response.data;
this.setState({
allHitDatas: allHitDatas
});
});
}
showNewDateRange(newStartDate, newEndDate) {
this.setState({
startDate: newStartDate,
endDate: newEndDate
// showDatePickerControls:false
}, () => {
this.dataChangeHelper();
});
}
handleImpactClick(d) {
console.log(d);
}
render () {
if (this.state.teams.length === 0 || this.state.players.length === 0) {
return (
<div className="no-data-container">
<div className="no-data-message">We don't have any data for you right now. Would you like
to add some players, teams, or devices?
</div>
<ul className="no-data-links">
<AdminSquare title="PLAYER ADMIN" icon="person" link="/player"/>
<AdminSquare title="TEAM ADMIN" icon="group" link="/team"/>
<AdminSquare title="DEVICE ADMIN" icon="sd_storage" link="/device"/>
</ul>
</div>
);
}
const { value, suggestions } = this.state;
const inputProps = {
placeholder: 'Search for a player',
value,
onChange: this.onChange
};
return (
<div>
<div className='admin-table-wrapper'>
<div className="homeview-subnav">
<div className="view-title">Team Data</div>
<DateRangeComponent
startDate={this.state.startDate}
endDate={this.state.endDate}
onDateChange={(newStartDate, newEndDate) => this.showNewDateRange(newStartDate, newEndDate)}
/>
<Autosuggest
suggestions={suggestions}
onSuggestionsUpdateRequested={this.onSuggestionsUpdateRequested}
shouldRenderSuggestions={this.shouldRenderSuggestions.bind(this)}
getSuggestionValue={this.getSuggestionValue.bind(this)}
renderSuggestion={this.renderSuggestion.bind(this)}
inputProps={inputProps}
/>
<button className="retrieve-file-trigger" onClick={this.retrieveFile.bind(this)}><i className='material-icons small file-icon'>file_download</i></button>
</div>
<div className="top-dashboard-data-container">
<div id="home-scatter-container">
<ScatterPlot
data={this.state.allHitDatas}
statOneTitle='HIC'
location='#home-scatter-container'
showScatterPlot={this.state.showScatterPlot}
sendHitData={(d) => this.handleImpactClick(d)}
/>
</div>
<DashboardStats
impactsRecorded={12456712}
devicesActive={27}
highestHic={234}
/>
</div>
<div className="table-wrapper">
<div className="table-title">TOP HICS</div>
<Table
className="table table-dashboard"
itemsPerPage={10}
pageButtonLimit={5}
noDataText="No data available for this filter set"
sortable
defaultSort={{column: 'hic', direction: 'desc'}}>
<Thead>
<Th column="name">
<strong className="name-header">NAME</strong>
</Th>
<Th column="hic">
<strong className="position-header">HIC</strong>
</Th>
</Thead>
{ this.renderReactableTwo(this.state.allHitDatas) }
</Table>
</div>
<div className="table-wrapper">
<div className="table-title">MOST HITS</div>
<Table
className="table table-dashboard"
itemsPerPage={10}
pageButtonLimit={5}
noDataText="No data available for this filter set"
sortable
defaultSort={{column: 'maxHic', direction: 'desc'}}>
<Thead>
<Th column="name">
<strong className="name-header">NAME</strong>
</Th>
<Th column="numHits">
<strong className="position-header"># OF HITS</strong>
</Th>
<Th column="maxHic">
<strong className="position-header">TOP HIC</strong>
</Th>
</Thead>
{ this.renderReactable(this.state.hitDatas) }
</Table>
</div>
</div>
</div>
);
}
}
答案 0 :(得分:0)
查看你的代码我会说没有redux的最佳选择是将日期范围状态移动到封装两个仪表板的父组件中,例如CoreLayout,并将范围作为props传递。
值得考虑切换到Redux,它起初看起来令人生畏,但是在你放手之后真的非常简单,确实让生活更轻松。