Тестируя React Native с помощью Redux и react-redux, я обнаружил, что содержимое дерева состояний Redux не отражается в отображать, если состояние не передается через контейнер.
Чтобы проверить это, я использую
- реактивный родной 0.19.0
- реакция-редукс 4.1.2
- редукс 3.1.7
как объясняет @alinzin в https://github.com/alinz/example-react-native-redux со всеми хитростями по настройке этого проекта. Есть ли другое хорошее решение?
В следующем примере показана простая строка как состояние в хранилище Redux и простое действие для увеличения строки.
Вот сокращение и данные в виде одной строки в состоянии.
//Reducer
const reducer = (state = { data: '[][][]' }, action = {}) => {
switch (action.type) {
case ENLARGE:
return Object.assign({}, state, {
data: state.data+'[]'
})
default:
return state
}
}
Зарегистрированное приложение похоже на это, ничего нового. Начальный маршрут запускает контейнер для App1Component. Это путь к хорошему состоянию привязки и компонентам (я верю)
export default class App extends Component {
render () {
return (
<Provider store={store}>
<Navigator style={{flex: 1}}
initialRoute={{
component: Container,
}}
renderScene={ (route, navigator) => {
const Component = route.component;
return (
<View style={{flex: 1, marginTop:40}}>
<Component navigator={navigator} route={route} {...route.passProps} />
</View>
);
}}
/>
</Provider>
)
}
}
Основное содержимое как для компонента App1Component, так и для App2Componenet является простым компонентом и просто отображает строку и показывает «кнопку» для отправки действия увеличения.
class MainContent extends Component{
render() {
return (
<View>
<Text>{this.props.data}-{this.props.data.length}</Text>
<TouchableOpacity onPress={()=>{this.props.enlarge()}} >
<Text>Click to Enlarge me!</Text>
</TouchableOpacity>
<Text> </Text>
</View>
)
}
}
Различий между компонентами App1 и App2 нет. Просто App1Component вызывается через Контейнер (и состояние привязки и действия), а App2Component вызывается (из App1Component) путем нажатия с помощью Navigator всех тех же реквизитов (то же самое в App1Component)
Вот App1Component с кнопкой для отправки следующей сцены в App2Component и передачи тех же реквизитов перед привязкой через Container.
class App1Component extends Component {
render() {
return (
<View>
<MainContent {...this.props}/>
<TouchableOpacity onPress={()=>{
this.props.navigator.push({
name: 'App2',
component: App2Component,
passProps: {...this.props}
})
}}>
<Text>Click to Forward to App2Component {'\n'}passing props through Navigator passProps</Text>
</TouchableOpacity>
</View>
)
}
}
Если вы нажмете здесь «увеличить», строка увеличится, и вы сможете увидеть действие, отраженное на экране. Также вы можете увидеть в хроме трассировку для регистратора избыточности.
Вот контейнер-оболочка для App1Component
const Container = connect(
(state) => ({
data: state.data
}),
(dispatch) => ({
enlarge: () => dispatch(enlarge())
})
)(App1Component)
А вот компонент 2, с кнопкой возврата. Если вы нажмете «увеличить» здесь, строка увеличится, конечно, вы можете увидеть след на хроме, но ... действие не отражается на экране.
class App2Component extends Component {
render() {
return (
<View>
<MainContent {...this.props}/>
<TouchableOpacity onPress={()=>{this.props.navigator.pop()}} >
<Text>Back to App1Component{'\n'}to see the change!</Text>
</TouchableOpacity>
</View>
)
}
}
После нажатия кнопки «Назад» вы увидите измененную строку на экране для App1Component.
Как видите, я неправильно понял что-то фундаментальное, но не то, что есть.
Должен ли я украшать все основные компоненты (страницы/сцены) контейнером? Почему неправильно передавать реквизиты (ранее привязанные к контейнеру) через passPros в Navigator? Действия рассылаются корректно, но на экране не отражается.
Любая помощь приветствуется. Спасибо