2016-10-30 2 views
1

나는 Refact가 & Redux 인 날씨 앱을 구축 중입니다. 나는 반응하지 않는 멍청이로서 미심쩍은 물로 탐험하기로 결정했다. & Redux. 저는 프레젠테이션 구성 요소와 데이터를 처리 할 각각의 컨테이너로 물건을 분할하고 있습니다. 이 문제를 해결하기 위해 몇 가지 문제가 있습니다. 내가 그것을 어떻게하려고하는지 나는 정말로 확신 할 수 없다.React + Redux : 프리젠 테이션을 데이터에서 분리하기

는 지금은 SearchBar, CurrentWeather, & Forecast 구성 요소와 나는에 해당 구성 요소를 통합하기 위해 노력하고있어 AppContainer 있습니다. 지금까지 AppContainerSearchBar 구성 요소가 통합되어 있으며 문제없이 작동합니다. 여기 내가 혼란스러워하는 곳이있다. 그래서 나는 컨테이너에 필요한 액션과 컴포넌트를 제공했고 컨테이너는 connected이었습니다. 그래서 사용자가 검색을하면 API 호출이 만들어지고 상태는 감속기를 통해 업데이트됩니다.

해당 데이터는 현재 mapStateToProps을 통해 사용 가능해야합니까?

사용자가 작업을 수행했지만 초기 렌더링시 사용하지 않은 후에 어떻게 데이터를 사용할 수 있습니까? AppContainer이이 세 가지 구성 요소를 렌더링하고 있다면 분명히 예상대로 렌더링하고 기능하도록 소품을 전달할 것입니다. 라이프 사이클을 사용할 수있는 곳이라고 생각하고 있습니다. 사용 방법이나 사용법을 확신 할 수 없습니다. AppContainer, SearcBar, & CurrentWeather에 대한 코드는 다음과 같습니다. CurrentWeather & Forecast은 거의 동일합니다 (API의 다른 끝점에서 다른 데이터를 제공함). 그래서 제공하지 않았습니다. 이 리팩터러를 사용하기로 결정하기 전에 제대로 작동한다는 것을 알고 있기 때문에 액션이나 리듀서도 제공하지 않았습니다. 이걸 풀기 위해 하나 이상의 컨테이너가 필요할지도 모릅니다. 모든 조언이나 방향은 크게 감사 드리며, 모두에게 감사하고 좋은 밤을 보내십시오.

** _weatherSearchSearchBar이 양식 요소이기 때문에 나는 event.preventDefault();이 있습니다. 이걸 제공해야합니까? event이 전달되는 것은 아니지만 term이 아니라고 생각합니다.

onSubmit={event => getWeather(event.target.value)}

앱 컨테이너 :

import React, { Component } from 'react'; 
import { connect } from 'react-redux'; 
import { fetchCurrentWeather, fetchForecast } from '../actions/actions'; 

import SearchBar from '../components/SearchBar'; 
import CurrentWeather from '../components/CurrentWeather'; 

class AppContainer extends Component { 

    _weatherSearch(term) { 
    event.preventDefault(); 
    // Here is where we go to fetch weather data. 
    this.props.fetchCurrentWeather(term); 
    this.props.fetchForecast(term); 
    } 

    render() { 
    const getWeather = term => {this._weatherSearch(term);}; 
    return (
     <div className="application"> 
     <SearchBar getWeather={getWeather}/> 
     <CurrentWeather /> 
     </div> 
    ); 
    } 
} 

const mapStateToProps = ({ current, forecast }) => { 
    return { 
    current, 
    forecast 
    } 
} 

export default connect(mapStateToProps, 
    { fetchCurrentWeather, fetchForecast })(AppContainer); 

SearchBar에 :

import React from 'react'; 

const SearchBar = ({ getWeather }) => { 
    return(
    <form className='input-group' onSubmit={event => getWeather(event.target.value)}> 
     <input 
     className='form-control' 
     placeholder='Search a US City' /> 
     <span className='input-group-btn'> 
     <button className='btn btn-secondary' type='submit'>Submit</button> 
     </span> 
    </form> 
); 
} 

export default SearchBar; 

CurrentWeather : * 참고 : 내가 가진 SearchBar의 형태 요소에 아래와 같이 event를 사용하고 있습니다 논리 또는 데이터 처리를 제거하지 않았으므로 아직 수정되지 않았습니다. CurrentWeather 빨간색은 아직 프리젠 테이션 전용 구성 요소입니다.

import React, {Component} from 'react'; 
import {connect} from 'react-redux'; 
import {unitConverter} from '../conversions/conversions_2.0'; 

export class CurrentWeather extends Component { 
    _renderCurrentWeather(cityData) { 
     const name = cityData.name; 
     const {temp, pressure, humidity} = cityData.main; 
     const {speed, deg} = cityData.wind; 
     const {sunrise, sunset} = cityData.sys; 
     return (
      <tr key={name}> 
       <td>{unitConverter.toFarenheit(temp)} F</td> 
       <td>{unitConverter.toInchesHG(pressure)}"</td> 
       <td>{humidity}%</td> 
       <td>{unitConverter.toMPH(speed)}mph {unitConverter.toCardinal(deg)}</td> 
      </tr> 
     ); 
    } 

    render() { 
     let currentWeatherData = []; 
     if (this.props.current) { 
      currentWeatherData = this.props.current.map(this._renderCurrentWeather); 
     } 
     return (
      <table className="table table-reflow"> 
       <thead> 
        <tr> 
         <th>Temperature</th> 
         <th>Pressure</th> 
         <th>Humidity</th> 
         <th>Wind</th> 
        </tr> 
       </thead> 
       <tbody> 
        {currentWeatherData} 
       </tbody> 
      </table> 
     ); 
    } 
} 

function mapStateToProps({current}) { 
    return {current}; 
} 

export default connect(mapStateToProps)(CurrentWeather); 

답변

2

렌더링 기능이 매우 동적입니다. 원하는 내용을 생략 할 수 있습니다.

누락 된 데이터를 처리하는 방법입니다. 아무 것도 표시하지 않거나 처음 검색 할 메시지를 표시하거나로드하는 경우 회 전자 또는 진동을 표시 할 수 있습니다.

위의 CurrentWeather을 숨기려면 위의 기술을 사용하여 구성 요소를 숨기려면 부울을 전달해야합니다. 반응 무시는 true, false, nullundefined입니다.

mapStateToProps에서 실제로 구성 요소 내부에서 사용할 데이터를 전달하는 것이 좋습니다. 코드에서 currentforecast을 전달하지만 사용하지 마십시오.

mapStateToProps, mapDispatchToProps 또는 props 데이터가 변경되면 Redux가 다시 렌더링합니다. 데이터를 반환하면 Redux가 필요하지 않을 때 다시 렌더링하도록 지시하지 않습니다.

2

저는 반응이 좋지 않은 멍청한 녀석입니다 :-) 나는 비슷한 문제에 직면했습니다.

는 지금까지 내가 말할 수있는, 당신이 만든 컨테이너/표상 분리가 좋아 보인다,하지만 당신도 한 단계 더 가서 컨테이너의 가져 오는 장착 분리 할 수 ​​있습니다.

내가 말하는 겁니다이 솔루션은 사람들이 다양하게 "고차 구성 요소"및 "래퍼 구성 요소"라고 부릅니다 : (아래의 코드가 테스트되지 않은 상태입니다 -이 설명을 위해 단지)

import {connect} from blah; 

const AppWrap = (Wrapped) => { 
    class AppWrapper extends Component { 
    constructor(props) { 
     super(props); 
     this.state = {foo: false}; 
    } 
    componentWillMount() { 
     this.props.actions.fooAction() 
     .then(() => this.setState({foo: false})); 
    } 
    render() { 
     return (<Wrapped {...this.props} foo={this.state.foo}/>); 
    } 
    } 

    function mapState(state) { blah } 
    function mapDispatch(dispatch) { blah } 

    return connect(mapState, mapDispatch)(AppWrapper); 
} 

export default AppWrap;  

상단에 = (Wrapped) => { 부분이 있음을 알 수 있습니다. 이것이 실제 "래핑 (wrapping)"을하는 것이고, 인자는 렌더 훅에서 참조하는 한 어떤 것이라도 이름을 붙일 수 있습니다.

이제 AppContainer 내부에 fooAction()이 완료되었음을 알리는 플래그 역할을하는 this.props.foo이 표시되며이를 사용하여 적절하게 프리젠 테이션 구성 요소를 렌더링 할 수 있습니다. fooAction이 완료 될 때까지 foo이 AppContainer로 전달 된 것은 false입니다.

코드에 난 그냥 말을 넣으려면, AppContainer은 다음과 같이 보일 수 있습니다

import AppWrapper from './AppWrapper'; 

class AppContainer extends Component { 
    constructor(props) { 
    super(props); 
    } 
    render() { 
    return (!this.props.foo) ? <div>bar</div> : (
     <div blah> 
     <SearchBar blah/> 
     <CurrentWeather blah/> 
     </div> 
    ); 
    } 
} 

export default AppWrapper(AppContainer); 

같은 래퍼 구성 요소를 사용의 장점은

  • 당신이 더 제어 할 수 있다는 것입니다 어떻게 그리고 정확히 데이터가 렌더링되는지에 대해
  • "로딩"메커니즘 및 로직에 대한 설명
  • 과 같은 기발한 문제를 피하십시오. the consequences을 처리해야하는후크가 있습니다.

는 HoCs에 대한 자세한 내용은이 블로그 게시물을 살펴보십시오 : https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750

+0

이'AppWrapper'는 다음 표상 구성 요소에 대한 로직을 포함하고 그냥 '통과 렌더링되는 하위 구성 요소 아래 props' 않습니다 AppContainer에서? – rockchalkwushock

+0

나는 논리를 어디에 두는 것이 우위라고 생각한다. 저는 여러분이 비동기 액션을 꺼내서'AppWrapper'에 넣고 액션의 "상태"를 소품으로 바꾸는 것을 제외하고는, 여러분이 이전에했던 것처럼 모든 것을 생각하고있었습니다. 요약하면 래퍼는 비동기 액션을 포함하고, 컨테이너는 로직을 포함하고, 컴포넌트는 jsx를 포함합니다. – omul

관련 문제