2016-06-29 5 views
0

Ich habe eine Layout-Komponente in reagieren (unten). Zwei meiner Komponenten, die über this.props.children (oder jetzt childrenWithProps) in diese Komponente injiziert werden, verfügen über eine von mir erstellte Datumsbereichskomponente, mit der der Benutzer den Datenbereich auswählen kann, der aus der API abgerufen wird. Eines ist ein Spieler-Dashboard und eines ist ein Team-Dashboard (Standardansicht und wird im zweiten Codeblock angezeigt). Wenn sich ein Benutzer im Team-Dashboard befindet und einen Player durchsucht und zu diesem Player-Dashboard wechselt, möchte ich den ausgewählten Datumsbereich (der als this.state.startDate und this.state.EndDate gespeichert ist) in das Player-Dashboard übernehmen. und dann umgekehrt. Ich denke, dass dies ein guter Anwendungsfall für Redux ist, aber bis jetzt habe ich es geschafft, nur Requisiten zu passieren und die Redux-Implementierung für den Datumsbereich scheint entmutigend zu sein. Jede Hilfe würde sehr geschätzt werden. Außerdem bin ich neu zu reagieren und weiß, dass ich eine Menge Neuformatierung machen muss.React.js behandelt eine Datumsänderung über Komponenten, die nicht Eltern/Kind sind

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> 
    ); 
    } 
} 

Hier ist das Team Armaturenbrett

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

Beachten Sie, dass Sie den Status überall verwalten können, wo Sie möchten (oder sogar überall, wo Sie nicht mögen). Sie können einfach eine globale Variable oder eine lokale Variable verwenden. Du könntest ein Objekt mit Requisiten mit Eigenschaften, die deine Reichweite beschreiben, durch den Baum ziehen. Dies könnte eine lokale Variable sein. Die Hauptprobleme bei diesem Ansatz sind, dass er nicht standardisiert und nicht erweiterbar ist. Redux löst beides. Wenn das zu viel Aufwand ist, verwenden Sie einfach [redux-schema] (https://www.npmjs.com/package/redux-schema) (Offenlegung: Ich schrieb es). – DDS

Antwort

0

auf den Code der Suche ich die beste Wette würde sagen, ohne redux ist den Datumsbereich Zustand in einen Elternteil zu bewegen Komponente, die beide Dashboards kapselt, wie beispielsweise das CoreLayout, und den Bereich als Requisiten durchlässt.

Es lohnt sich, in den Wechsel zu Redux zu schauen, es sieht auf den ersten Blick entmutigend aus, aber es ist wirklich super einfach, nachdem man es versucht hat, macht das Leben leichter.

+0

Ja, das war meine erste Annäherung, aber dann wurde mir klar, dass es eine Reihe von Kindansichten gibt, bei denen es sich um Admin-Ansichten innerhalb von CoreLayout handelt, die nicht den Datumsbereich und die Suche enthalten. – hifilorau

+0

Ich denke, wo ich es mit Redux verliere versuche, meinen Reducer zu schreiben. In der ursprünglichen Inkrementiereraktion, die ich betrachte, habe ich eine Zeile, die wie folgt aussieht: export const increment = createAction (INCREMENT, (value = 1) => value); aber ich weiß, dass ich etwas mehr wie 'export const startDate = brauche createAction (DATE_CHANGE, (Wert = 1) => Wert); 'aber nicht sicher, wie der Wertteil der Anweisung behandelt wird. Ich nehme an, dass es das Datum von this.state.startDate in einer meiner Komponenten erhalten wird. – hifilorau

+0

Also ja, hier geht es um wo ich mit redux verloren bin. – hifilorau