通过Redux Connect订购单个减速器仍可将所有减速器交付给组件

时间:2018-01-20 04:00:22

标签: reactjs react-native redux

我有一个有9个减速器的商店。我只希望我的组件听取其中一个discoverSearch。使用mapStateToProps的简写版本,这是我的代码。但是,该组件仍在componentWillReceiveProps中传递所有减速器。

组件

import React from 'react'
import { connect } from 'react-redux'
import { View, Text, Animated, Dimensions } from 'react-native'

const _ = require('lodash')

import colors from '../../Color'
import DiscoverSearchResultChannel from './DiscoverSearchResultChannel'
import DiscoverSearchResultEpisode from './DiscoverSearchResultEpisode'

const { height, width } = Dimensions.get('window') 

class DiscoverSearchResultsContainer extends React.Component {

  constructor() {
    super()

    this.generateResultsList = this.generateResultsList.bind(this)

  }

  generateResultsList(results, type) {
    const components = []
    for (let i = results.length - 1; i >= 0; i--) {
      if (type === 'CHANNEL') {
        const result = 
        (<DiscoverSearchResultChannel 
          entry={results[i]} 
          key={`dsearch-${results[i].id}`} 
          navigation={this.props.navigation}
        />)
        components.push(result)
      } else if (type === 'EPISODE') {
        const result = 
        (<DiscoverSearchResultEpisode 
          entry={results[i]}
          key={`dsearch-${results[i].id}`} 
          navigation={this.props.navigation}
        />)

        components.push(result)
      }

    }
    return components
  }

  render() {

    const { episodes, channels } = this.props.discoverSearch.results

    return (
      <Animated.ScrollView 
        style={styles.shell} 
        contentContainerStyle={styles.innerContent}
      >
      <Text style={styles.divider}>Podcasts</Text>
      {
        _.isUndefined(channels) ? null : this.generateResultsList(channels, 'CHANNEL')
      }
      <Text style={styles.divider}>Episodes</Text>
      {
        _.isUndefined(episodes) ? null : this.generateResultsList(episodes, 'EPISODE')
      }
      </Animated.ScrollView> 
    )
  }

}


export default connect(store => (
{ discoverSearch: store.discoverSearch },
  dispatch => dispatch
  ))(DiscoverSearchResultsContainer)

商店

import { applyMiddleware, createStore } from 'redux'
import { createLogger } from 'redux-logger'
import thunk from 'redux-thunk'
import promise from 'redux-promise-middleware'

import combinedReducers from './reducers/CombineReducers'

const middleware = applyMiddleware(
  thunk,
  createLogger(),
  promise()
)

export default createStore(combinedReducers, middleware)

DiscoverSearchReducer

const initialState = {
  results: []
}
const DiscoverSearchReducer = (state = initialState, action) => {

  let newState    

  switch (action.type) {

    case 'DISCOVER_SEARCH_REQUEST_OUT':
      // TODO
      break
    case 'DISCOVER_SEARCH_RETURN':
      newState = {
        ...state,
        results: action.payload
      }
      break
    default:
      return state 
  }

  return newState
}

减速

export default combineReducers({
  network: NetworkReducer,
  audioPlayer: AudioPlayerReducer,
  fileHandler: FileHandlerReducer,
  currentTrack: CurrentTrackReducer,
  trackQueue: TrackQueueReducer,
  asyncStatus: AsyncStatusReducer,
  makeClip: MakeClipReducer,
  userProfile: UserProfileReducer,
  scrollListener: ScrollListenReducer,
  userClips: UserClipsReducer,
  discoverSearch: DiscoverSearchReducer,
})

应用程序录入

class App extends React.Component {

  componentWillMount() {

    // TODO
    // Initialize Firebase => get UID then... 
      store.dispatch(fetchUser('7713BNBNPODPIE'))
  }

  componentDidMount() {
    TrackPlayer()
  }

  render() {
    return (
      <Provider store={store} >
        <View style={{ flex: 1 }}>
          <Navigation />
          <BottomPlayer />
        </View>
      </Provider>
    )
  }
}

export default App

Redux的连接件对我来说有点新鲜,所以我可能会遗漏一些明显的东西?

编辑: 添加了App.js入口点 添加了完整的DiscoverSearchResultsContainer组件减去styles

3 个答案:

答案 0 :(得分:3)

错误在您的连接功能中:

export default connect(store => (
  { discoverSearch: store.discoverSearch },
    dispatch => dispatch
  ))(DiscoverSearchResultsContainer)

你的括号错了,这相当于:

connect(store => {
  // this does nothing
  { discoverSearch: store.discoverSearch };
  return dispatch => dispatch;
})(...)

实际上与

相同
connect(state => state)(...)

你可能想写的是:

connect(store = ({ discoverSearch: store.discoverSearch }), 
  dispatch => dispatch)(...)

编辑:删除不必要的调度

如评论所示,映射调度是没用的,你可以做到

const mapStateToProps = state => ({ discoverSearch: state.discoverSearch });
connect(mapStateProps)(Component);

答案 1 :(得分:2)

使用连接最简单的方法是将mapStateToPropsmapDispatchToProps分离到自己的函数中,以避免出现语法错误,如果你无论如何都要将dispatch作为第二个参数返回不使用它,因为如果要连接的第二个参数为空,则默认返回dispatch。

根据 connect documentaion

  

[mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function):如果传递了一个对象,则假定其中的每个函数   成为Redux动作创作者。具有相同函数名的对象,   但是每个动作创建者都会被包裹在一个调度呼叫中,所以他们可以   直接调用,将​​合并到组件的道具中。

     

如果传递了一个函数,它将作为第一个函数发送   参数。你可以归还一个以某种方式使用的对象   发送以您自己的方式绑定动作创建者。 (提示:你可以使用   来自Redux的bindActionCreators()助手。)

     

如果您的mapDispatchToProps函数被声明为两个   参数,它将被调用作为第一个参数和   道具作为第二个参数传递给连接组件,   并且只要连接的组件收到新的,就会重新调用   道具。 (第二个参数通常称为ownProps by   约定。)

     

如果您不提供自己的mapDispatchToProps功能或对象   完整的动作创建者,默认mapDispatchToProps   实现只是将调度注入组件的道具。

您可以使用

等连接状态
const mapStateToProps = store => {
    return { discoverSearch: store.discoverSearch }
}

export default connect(mapStateToProps)(DiscoverSearchResultsContainer)

使用连接时

export default connect(store => (
      { discoverSearch: store.discoverSearch },
        dispatch => dispatch
))(DiscoverSearchResultsContainer)

您确实将()放在了错误的位置,因为您想要返回{ discoverSearch: store.discoverSearch }而不是{ discoverSearch: store.discoverSearch }, dispatch => dispatch。它应该是

export default connect(store => (
      { discoverSearch: store.discoverSearch })
)(DiscoverSearchResultsContainer)

以上代码段与

相同
export default connect(store => {
          return { discoverSearch: store.discoverSearch }
      }
)(DiscoverSearchResultsContainer)

这就是你所需要的。但是你必须采用第一种方法

答案 2 :(得分:0)

你的DiscoverSearchReducer是否有可能为每次发送返回一个新对象,即使在无操作时也是如此?

function reduceSomething(state, action) {
     if action.type == "forMe":    
       return {action.payload}
     else
       return {...state}
}

而不是:

 return state

因为前者会为每个调度提供一个新对象,具有预期内容,但是connect将无法禁止将props传递给您的组件。

这是一个奇怪的,但它符合你的症状。