redux: Component not updating in React Native
I’ve followed the tutorial so far and I have to admit that, albeit the Flux/Redux architecture has a steep learning curve, I managed to successfully make almost everything work very quickly and understanding all the fundamental things.
However, the component I’m rendering is not updating when an action is dispatched.
I want to add elements to a list. Here’s the code I made so far:
Actions.js
:
export const ADD_ELEMENT = 'ADD_ELEMENT'
export function addElement (element) {
return { type: ADD_ELEMENT, element }
}
Reducers.js
:
import { ADD_ELEMENT } from 'Actions'
import { combineReducers } from 'redux'
const initialState = {
elements: [
{id: 1, element: 'thing'},
{id: 2, element: 'anotherThing'}
],
}
function elements (state = initialState.elements, action) {
switch (action.type) {
case ADD_ELEMENT:
return [...state, action.element]
default:
return state
}
}
const boatApp = combineReducers({
elements
})
export default boatApp
index.ios.js
:
// ...Imports
const logger = createLogger()
const createStoreWithMiddleware = applyMiddleware(thunk, promise, logger)(createStore)
const store = createStoreWithMiddleware(boatApp)
class boat extends Component {
render () {
return (
<Provider store={store}>
{() => <TabBar />}
</Provider>
)
}
}
Then, inside the <TabBar />
component I have a view with a React Native <ListView />
component that has to display the list of elements:
import React, { Component, View, Text, ListView, StyleSheet } from 'react-native'
import { connect } from 'react-redux/native'
@connect(state => ({ elements: state.elements }))
class ElementItemsList extends Component {
constructor (props) {
super(props)
let dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
})
this.state = {
elements: props.elements,
dataSource: dataSource.cloneWithRows(props.elements)
}
}
_renderRow (rowData) {
return (<Text>{rowData.element}</Text>)
}
render () {
return (
<View style={{flex: 1}}>
<ListView style={styles.container}
contentInset={{top: 0}}
automaticallyAdjustContentInsets={false}
dataSource={this.state.dataSource}
renderRow={(rowData) => this._renderRow(rowData)}
/>
<Text style={{flex: 1}}>
{this.state.elements}
</Text>
</View>
)
}
}
The thing is that I need to update this.state.dataSource
in order to make <ListView />
update it’s content. Any clue about how I can update the state when the elements are updated?
Update
Just FYI, there is also a <Text />
component I put after the ListView that doesn’t need the dataSource
update, it prints this.state.elements
and it’s not updating also.
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 23 (5 by maintainers)
Alas, I don’t know enough about what
dataSource
is to help you. The problem is not Redux-specific, and is described in Props in getInitialState is an anti-pattern. You’ll get newprops
from Redux every time store updates, but you don’t use them: you only usestate
which you initialize once.Does something like this help?
Note that unlike
componentDidUpdate()
, asetState()
call insidecomponentWillReceiveProps()
won’t trigger another render, so it will be faster.Still, it looks rather weird to me, but again, I don’t know enough about React Native or
dataSource
.I ended up doing something like this.
Couldn’t you just create a new DataSource instance in the render method? or do something like this:
Or does that result in performance issues?
(Disclaimer: I don’t know a lot about React Native)
(Small suggestion:
elements
is confusing naming because I thought you’re referring to React elements, i.e. stuff you get fromReact.createElement
. Better to rename it toitems
.)Instead of setting an attribute against the row, maintain a “selected_row” key:
{selected_row: row_id}
@sompylasar @luqmaan @alvaromb This solution didn’t work for me,i’m using react native’s Navigator component to render my scenes, could this be the cause, although when JavaScript Set interval to console log the same prop data it displays the new state when changed, can’t seem to tell whats wrong here.
This is my component’s class:
Someone please help!
I moved
outside the function. Works fine for me. The problem I’m having is if I want to press on the row and make it active/checked, I have to go through the whole list in the reducer find the row and change the state on it, doesn’t seem to be very efficient… Any opinion on how or where properly to set
selected: true/false
on the row?