如何使用redux在prop更改上重新渲染子组件?

时间:2016-11-03 00:41:14

标签: react-native redux immutable.js

我有一个使用redux和immutable js的本机应用程序。当我从主屏幕发送一个动作时,它会通过我的动作,我的reducer,然后回到我的容器,但是,视图没有更新,并且从不调用componentWillReceieveProps。此外,主屏幕是一个列表,其项目是子组件项目。以下是该问题的相关代码,如果您想了解更多,请告诉我。

使用数据渲染行:

renderRow(rowData) {
    return (
        <Item item={ rowData } likePostEvent={this.props.likePostEvent} user={ this.props.user } removable={ this.props.connected } />
    )
}

Item.js调度动作的部分,并显示结果:

<View style={{flex: 1, justifyContent:'center', alignItems: 'center'}}>
                        <TouchableOpacity onPress={ this.changeStatus.bind(this, "up") }>
                            <Image source={require('../img/up-arrow.png')} style={s.upDownArrow} />
                        </TouchableOpacity>
                        <Text style={[s.cardText,{fontSize:16,padding:2}]}>
                            { this.props.item.starCount }
                        </Text>
                        <TouchableOpacity onPress={ this.changeStatus.bind(this, "down") }>
                            <Image source={require('../img/up-arrow.png')} style={[s.upDownArrow,{transform: [{rotate: '180deg'}]}]} />
                        </TouchableOpacity>
                    </View>

调度的动作转到firebase,它有一个onChange处理程序,用于调度另一个动作。

减速器:

const initialState = Map({
 onlineList: [],
 offlineList: [],
 filteredItems: [],
 connectionChecked: false,
 user: ''
})
...
...
case ITEM_CHANGED:
list = state.get('onlineList')
if(state.get('onlineList').filter((e) => e.id == action.item.id).length > 0){
  let index = state.get('onlineList').findIndex(item => item.id === action.item.id);
  list[index] = action.item
  list = list.sort((a, b) => b.time_posted - a.time_posted)
}
return state.set('onlineList',  list)
            .set('offlineList', list)

容器:

function mapStateToProps(state) {
 return {
    onlineItems: state.items.get('onlineList'),
    offlineItems: state.items.get('offlineList'),
    filteredItems: state.items.get('filteredItems'),
    connectionChecked: state.items.get('connectionChecked'),
    connected: state.items.get('connected'),
    user: state.login.user
  }
}

我在哪里连接onChange:

export function getInitialState(closure_list) {
  itemsRef.on('child_removed', (snapshot) => {
    closure_list.removeItem(snapshot.val().id)
  })
  itemsRef.on('child_added', (snapshot) => {
    closure_list.addItem(snapshot.val())
  })

  itemsRef.on('child_changed', (snapshot) => {
    closure_list.itemChanged(snapshot.val())
  })

  connectedRef.on('value', snap => {
    if (snap.val() === true) {
      closure_list.goOnline()
    } else {
      closure_list.goOffline()
    }
  })
  return {
    type: GET_INITIAL_STATE,
    connected: true
  }
}

调用get initial state:

this.props.getInitialState({
        addItem: this.props.addItem,
        removeItem: this.props.removeItem,
        goOnline: this.props.goOnline,
        goOffline: this.props.goOffline,
        itemChanged: this.props.itemChanged
    })

欢迎任何建议,非常感谢!

2 个答案:

答案 0 :(得分:0)

您的问题的根源可能在于对Firebase的调用。如果是异步调用,则返回回调可能不会返回您的操作可以使用的内容。

你知道它是否会回归承诺吗?如果是这种情况,则存在处理此类调用的中间件并停止调用操作,直到收到正确的响应。一个这样的中间件是Redux-Promise

答案 1 :(得分:0)

  import React from 'react';
import ReactDOM from 'react-dom';
import { createStore,combineReducers } from 'redux' //Redux.createStore
import { Provider,connect } from 'react-redux';



//Функція яка змінює store
const hello = (state= {message:'none'}, action) => {
    switch (action.type) {
        case 'HELLO':
            return Object.assign({}, state, {message:"hello world"});
            break
        case  'buy':
            return Object.assign({}, state, {message:"buy"});
            break;
        case 'DELETE':
            return Object.assign({}, state, {message:"none"});
            break;
        default :
            return state;
    }
};


const price = (state= {value:0}, action) => {
    switch (action.type) {
        case 'HELLO':
            return Object.assign({}, state, {value: state.value + 1 });
            break;
        default :
            return Object.assign({}, state, {value:0});
    }
};

const myApp = combineReducers({
    hello,price
});

//створюємо  store
let store = createStore(myApp);

let unsubscribe = store.subscribe(() => console.log(store.getState()))



//VIEW
class App extends React.Component {

    constructor(props) {
        super(props);
    }

    render() {
        return (
            <div>

                <p>value: {this.props.price}</p>

                <a href="#" onClick={this.props.onClick}>click</a><b>{this.props.message}</b>
            </div>
        )
    }
}


//mapStateToProps() для чтения состояния и mapDispatchToProps() для передачи события

const mapStateToProps = (state, ownProps) => {
    return {
        message: state.hello.message,
        price: state.price.value
    }
};
const mapDispatchToProps = (dispatch, ownProps) => {
    return {
            onClick: () => {

                var items= ['HELLO','buy','DELETE','error']
                var item = items[Math.floor(Math.random()*items.length)];

                dispatch({ type: item })
        }
}
}


const ConnectedApp = connect(
    mapStateToProps,
    mapDispatchToProps
)(App);




ReactDOM.render(
    <Provider store={store}>
        <ConnectedApp />
    </Provider>,
    document.getElementById('app')
);