2016-04-21 62 views
5

Tôi vẫn còn tương đối mới đối với React/Redux nên xin lỗi nếu đây là một câu hỏi đơn giản nhưng tôi vẫn chưa tìm được giải pháp.Trạng thái React/Redux trống trong lần gọi hành động thứ hai

Tôi có một hai hành động:

// DESTINATIONS 
// ============================================== 

export const DESTINATION_REQUEST = 'DESTINATION_REQUEST'; 
export const DESTINATION_SUCCESS = 'DESTINATION_SUCCESS'; 
export const DESTINATION_FAILURE = 'DESTINATION_FAILURE'; 

export function loadDestination (params, query) { 

    const state = params.state ? `/${params.state}` : ''; 
    const region = params.region ? `/${params.region}` : ''; 
    const area = params.area ? `/${params.area}` : ''; 

    return (dispatch) => { 
     return api('location', {url: `/accommodation${state}${region}${area}`}).then((response) => { 
      const destination = formatDestinationData(response); 

      dispatch({ 
       type: DESTINATION_SUCCESS, 
       destination 
      }); 
     }); 
    }; 
} 





// PROPERTIES 
// ============================================== 

export const PROPERTIES_REQUEST = 'PROPERTIES_REQUEST'; 
export const PROPERTIES_SUCCESS = 'PROPERTIES_SUCCESS'; 
export const PROPERTIES_FAILURE = 'PROPERTIES_FAILURE'; 

export function loadProperties (params, query, rows = 24) { 

    return (dispatch, getState) => { 

     console.log(getState()); 

     return api('search', {locationId: xxxxxx, rows: rows}).then((response) => { 
      const properties = response.results.map(formatPropertiesData); 

      dispatch({ 
       type: PROPERTIES_SUCCESS, 
       properties 
      }); 
     }); 
    }; 
} 

chúng được kết hợp với gia giảm tương đối của chúng:

// DESTINATIONS REDUCERS 
// ============================================== 

export default function destination (state = [], action) { 
    switch (action.type) { 
    case DESTINATION_SUCCESS: 
     return action.destination; 
    default: 
     return state; 
    } 
} 





// PROPERTIES REDUCERS 
// ============================================== 

export default function properties (state = [], action) { 
    switch (action.type) { 
    case PROPERTIES_SUCCESS: 
     return action.properties; 
    default: 
     return state; 
    } 
} 

và chúng được gọi là từ bên trong một thành phần (connectDataFetchers vòng qua các hành động gọi và trả về họ thành phần cho hiển thị bên máy chủ):

// PROPTYPES 
 
// ============================================== 
 

 
Search.propTypes = { 
 
    destination: PropTypes.object.isRequired, 
 
    properties: PropTypes.array.isRequired 
 
}; 
 

 

 

 

 

 
// ACTIONS 
 
// ============================================== 
 

 
function mapStateToProps ({destination, properties}) { 
 
    return {destination, properties}; 
 
} 
 

 

 

 

 

 
// CONNECT & EXPORT 
 
// ============================================== 
 

 
export default connect(mapStateToProps)(
 
    connectDataFetchers(Search, [loadDestination, loadProperties]) 
 
);

export default function connectDataFetchers (Component, actionCreators) { 
 
    return class DataFetchersWrapper extends React.Component { 
 
     static propTypes = { 
 
      dispatch: React.PropTypes.func.isRequired, 
 
      location: React.PropTypes.object.isRequired, 
 
      params: React.PropTypes.object.isRequired 
 
     }; 
 
     
 
     static fetchData (dispatch, params = {}, query = {}) { 
 
      return Promise.all(
 
       actionCreators.map((actionCreator) => dispatch(actionCreator(params, query))) 
 
      ); 
 
     } 
 

 
     componentDidMount() { 
 
      DataFetchersWrapper.fetchData(
 
       this.props.dispatch, 
 
       this.props.params, 
 
       this.props.location.query 
 
      ); 
 
     } 
 

 
     render() { 
 
      return (
 
       <Component {...this.props} /> 
 
      ); 
 
     } 
 
    }; 
 
}

tôi cần để chạy các hành động đầu tiên (loadDestination) mà sẽ trả về một ID sau đó cần phải rồi gửi cho action giây để tải các thuộc tính với vị trí đó ID.

Nếu tôi mã hóa vị tríID, điều này hoạt động tốt, nhưng nếu tôi cố gắng truy cập vào trạng thái ở loadProperties qua getState() thì trả về { destination: [], properties: [] }.

Có cách nào để truy cập giá trị từ hành động đầu tiên qua tiểu bang không?

SOLUTION

Managed để có được điều này để làm việc sau khi gợi ý từ @ pierrepinard_2

Tôi tạo ra một hành động mới mà công văn hai hành động khác theo thứ tự tôi cần:

// SEARCH 
 
// ============================================== 
 

 
export function loadSearch (params, query) { 
 
    
 
    return (dispatch) => { 
 
     return dispatch(
 
      loadDestination(params, query) 
 
     ).then(() => { 
 
      return dispatch(
 
       loadProperties(params, query) 
 
      ) 
 
     }) 
 
    } 
 
} 
 

 
// DESTINATIONS 
 
// ============================================== 
 

 
export const DESTINATION_REQUEST = 'DESTINATION_REQUEST'; 
 
export const DESTINATION_SUCCESS = 'DESTINATION_SUCCESS'; 
 
export const DESTINATION_FAILURE = 'DESTINATION_FAILURE'; 
 

 
export function loadDestination (params, query) { 
 

 
    const state = params.state ? `/${params.state}` : ''; 
 
    const region = params.region ? `/${params.region}` : ''; 
 
    const area = params.area ? `/${params.area}` : ''; 
 

 
    return (dispatch) => { 
 
     return api('location', {url: `/accommodation${state}${region}${area}`}).then((response) => { 
 
      const destination = formatDestinationData(response); 
 
      
 
      dispatch({ 
 
       type: DESTINATION_SUCCESS, 
 
       destination 
 
      }); 
 
     }); 
 
    }; 
 
} 
 
    
 
    // PROPERTIES 
 
// ============================================== 
 

 
export const PROPERTIES_REQUEST = 'PROPERTIES_REQUEST'; 
 
export const PROPERTIES_SUCCESS = 'PROPERTIES_SUCCESS'; 
 
export const PROPERTIES_FAILURE = 'PROPERTIES_FAILURE'; 
 

 
export function loadProperties (params, query, rows = 24) { 
 

 
    return (dispatch, getState) => { 
 
     return api('search', {locationId: getState().destination.id, rows: rows}).then((response) => { 
 
      const properties = response.results.map(formatPropertiesData); 
 

 
      dispatch({ 
 
       type: PROPERTIES_SUCCESS, 
 
       properties 
 
      }); 
 
     }); 
 
    }; 
 
}

sau đó trong thành phần tôi chỉ yêu cầu một hành động:

export default connect(mapStateToProps)(
 
    connectDataFetchers(Search, [loadSearch]) 
 
);

+0

Bạn có thể chia sẻ cách cuộc gọi tảiĐăng ký & loadProperties? –

+0

@DamienLeroux - Tôi đã thêm một số mã khác từ thành phần tìm kiếm cộng với hàm 'connectDataFetchers' – Paul

Trả lời

3

Bạn sử dụng Promise.all() trong phương pháp fetchData() của bạn: hành động của bạn được gửi đi song song, không cái khác.

Để đảm bảo rằng bạn gọi đích đến đầu tiên sau đó là thuộc tính, bạn nên tạo một trình tạo hành động không đồng bộ cụ thể cho thành phần Tìm kiếm của mình. Trình tạo hành động không đồng bộ này sẽ triển khai các yêu cầu liên tiếp bạn cần trong trường hợp này.

+0

Tôi đã thử gọi ban đầu hai hàm trong một hàm riêng biệt nhưng không gắn với các biến tương ứng trong mapStateToProps. Làm cách nào để duy trì mối quan hệ đó? – Paul

+0

Tôi không hiểu ý bạn là gì. Hàm mapStateToProps() truy xuất các đạo cụ của bạn từ trạng thái một và duy nhất của ứng dụng của bạn. Có vấn đề gì với thứ tự mà các yêu cầu api được nhận không? Nếu bạn sử dụng phần mềm trung gian redux-thunk để xử lý yêu cầu không đồng bộ của bạn và muốn chuỗi dispatch dispatch() gọi với(), hãy đảm bảo luôn trả lời lời hứa trong người tạo hành động không đồng bộ của bạn (thêm thông tin trong https://github.com/gaearon/redux-thunk # composition). Ví dụ, bạn nên "trả lại công văn (...);" trong những người sáng tạo hành động của bạn. –

+0

Cảm ơn @ pierrepinard_2 - tuân theo gợi ý redux-thunk tôi đã làm việc này và đã thêm giải pháp ở trên – Paul

0

Tôi đồng ý với @ pierrepinard_2.

Sử dụng promise.map từ bluebird, bạn sẽ có thể gọi tất cả lời hứa đã được đồng bộ hóa.

Điều này post on stack overflow sẽ giúp bạn về vấn đề đó.

Hãy cho chúng tôi biết nếu nó hoạt động

Các vấn đề liên quan