2016-06-29 2 views
0

응답 (아래)에 레이아웃 구성 요소가 있습니다. this.props.children (또는 이제 childrenWithProps)을 통해이 구성 요소에 주입되는 두 구성 요소에는 사용자가 teh API에서 가져온 데이터 범위를 선택할 수 있도록 만든 날짜 범위 구성 요소가 있습니다. 하나는 플레이어 대시 보드이고 다른 하나는 팀 대시 보드입니다 (기본보기 및 두 번째 코드 블록에 표시됨). 사용자가 팀 대시 보드에 있고 플레이어를 검색하여 해당 플레이어 대시 보드로 이동하면 선택한 날짜 범위 (this.state.startDate 및 this.state.EndDate로 저장 됨)가 플레이어 대시 보드로 옮겨지기를 원합니다. 그 반대의 경우도 마찬가지입니다. 나는 이것이 redux를위한 좋은 유스 케이스라고 느낀다. 그러나 지금까지 나는 단지 소품을 지나가는 것에 의해 그럭저럭 도착했다. 그리고 날짜 범위를위한 redux 실시는 위압적 인 것처럼 보인다. 어떤 도움이라도 대단히 감사 할 것입니다. 또한, 나는 반응하고 내가 재 형식화의 상당한 금액을해야 알 수있는 새로운이야. 여기 부모/자식이 아닌 구성 요소에서 날짜 변경을 처리하는 React.js

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

는 REDUX 부모에 날짜 범위 상태를 이동하는 것입니다없이 나는 최선을 말하고 싶지만 코드를 보면 팀 대시 보드

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

좋아하는 곳 어디에서나 상태를 관리 할 수 ​​있습니다 (또는 마음에 들지 않는 곳에서도). 글로벌 변수 또는 로컬 변수를 사용할 수 있습니다. 범위를 설명하는 몇 가지 속성을 가진 소도구를 사용하여 개체를 트리 아래로 전달할 수 있습니다. 이것은 지역 변수가 될 수 있습니다. 이 접근 방식의 주요 문제점은 표준이 아니며 확장 할 수 없다는 점입니다. Redux는이 두 가지를 모두 해결합니다. 이것이 너무 번거 롭다면 [redux-schema] (https://www.npmjs.com/package/redux-schema)를 사용하십시오 (공개 : 내가 썼습니다). – DDS

답변

0

입니다 예를 들어 CoreLayout과 같이 대시 보드를 모두 캡슐화하고 범위를 소품으로 전달하는 구성 요소입니다.

Redux로 전환하는 것을 살펴볼 가치가 있습니다. 처음에는 힘들어 보이지만, 실제로 실행하면 슈퍼가 간단합니다.

+0

그래, 그게 내 첫 접근 이었지만, 그때 거기에 날짜 범위와 검색이없는 CoreLayout 내부의 관리보기입니다 자식보기 잔뜩 깨달았다. – hifilorau

+0

나는 redux와 함께 그것을 잃어 버릴 것 같아 내 감속기를 작성하려고합니다. 원래의 증분 작업에서 나는'export const increment = createAction (INCREMENT, (value = 1) => value);와 같은 줄을 보았습니다. 그러나'export const startDate = createAction (DATE_CHANGE, (value = 1) => value);하지만 명령문의 값 부분을 처리하는 방법을 모릅니다. 내 구성 요소 중 하나에서 this.state.startDate로부터 날짜를받는 것으로 가정합니다. – hifilorau

+0

그래, 이건 내가 희생자와 함께 길을 잃은 곳이다. – hifilorau