将 react-native-router-flux 与 redux 一起使用,如何更新视图组件中的状态?
Using react-native-router-flux with redux, how to update state in the view component?
问题:
我尝试将 redux 与 react-native-router-flux 提供的路由结合使用。
简而言之,它不起作用:
- redux 状态修改不会出现在视图中,但可以成功记录到控制台
- 每次执行操作时,都会重新创建包含场景的整个组件树,这会导致控制台中出现大量警告,表明已经创建了具有键“xyz”的场景。
我做了什么:
我使用了react-native-router-flux官方的示例应用,并添加了一个简单的基于redux的反例:
- 一个简单的状态:“计数器”(可能是一个整数)
- reducer 和 action(递增、递减)
下面我将展示一些代码,但也可以找到我的 example application on github, please feel free to check it out: https://github.com/itinance/react-native-router-flux。 "Example" 目录是原始示例应用程序。 "ExampleRedux" 是带有 redux 堆栈和示例 reducer(计数器)的示例的副本,我在这里谈论的是什么。
主应用程序 提供程序和存储的组件:
import * as reducers from './components/reducers';
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
const reducer = combineReducers(reducers);
const store = createStoreWithMiddleware(reducer);
export default class Example extends React.Component {
render() {
return (
<Provider store={store}>
<ExampleContainer/>
</Provider>
);
}
}
我的减速器:
const initialState = {
count: 0
};
export default function counter(state = initialState, action = {}) {
switch (action.type) {
case "INCREMENT":
console.log("do increment", state,
{
...state,
count: state.count + 1
}
);
return {
...state,
count: state.count + 1
};
case "DECREMENT":
return {
...state,
count: state.count - 1
};
default:
return state;
}
}
redux'connect'的内部应用容器:
我将状态和动作传递给场景组件:
<Scene key="launch" component={Launch} title="Launch" initial={true} state={state} {...actions} />
这个ExampleContainer的全部代码:
class ExampleContainer extends React.Component {
constructor(props) {
super(props);
}
render() {
const { state, actions } = this.props;
console.log("Props", this.props, state, actions); // everything ok here
return <Router createReducer={reducerCreate}>
<Scene key="modal" component={Modal} >
<Scene key="root" hideNavBar={true}>
<Scene key="echo" clone component={EchoView} />
<Scene key="register" component={Register} title="Register"/>
<Scene key="home" component={Home} title="Replace" type="replace"/>
<Scene key="launch" component={Launch} title="Launch" initial={true} state={state} {...actions} />
.... lots of other scenes ...
</Scene>
</Scene>
<Scene key="error" component={Error}/>
</Scene>
</Router>;
}
}
export default connect(state => ({
state: state.counter
}),
(dispatch) => ({
actions: bindActionCreators(actions, dispatch)
})
)(ExampleContainer);
这是非常简单的 LaunchScreen,具有简单的计数器功能(以及用于演示路由的示例路由):
class Launch extends React.Component {
constructor(props) {
super(props);
console.log(props);
}
render(){
const { state, increment, decrement } = this.props;
console.log("Props 2: ", this.props, state, increment, decrement);
return (
<View {...this.props} style={styles.container}>
<Text>Launch page</Text>
<Text>{state.count}</Text>
<Button onPress={increment}>Increment</Button>
<Button onPress={()=>Actions.login({data:"Custom data", title:"Custom title" })}>Go to Login page</Button>
<Button onPress={Actions.register}>Go to Register page</Button>
<Button onPress={Actions.register2}>Go to Register page without animation</Button>
<Button onPress={()=>Actions.error("Error message")}>Popup error</Button>
<Button onPress={Actions.tabbar}>Go to TabBar page</Button>
<Button onPress={Actions.pop}>back</Button>
</View>
);
}
}
点击增量按钮时,动作被完美调度。在控制台中,可以成功记录新状态。每次单击它都会一个一个递增。但不在视图中。
当我省略路由器和场景并仅将启动屏幕作为单个组件激活时,一切正常。
问题:
如何使这个 redux 应用程序工作,视图将正确更新它们的状态?
为了完整起见,整个代码可以在github.
上找到
您可能忘记将 Launch
组件连接到商店。您想要做的与您在 ExampleContainer
中所做的类似,即
export default connect(state => ({
state: state.counter
}),
(dispatch) => ({
actions: bindActionCreators(actions, dispatch)
})
)(Launch);
然后正确的值将显示在您的日志中
问题:
我尝试将 redux 与 react-native-router-flux 提供的路由结合使用。
简而言之,它不起作用:
- redux 状态修改不会出现在视图中,但可以成功记录到控制台
- 每次执行操作时,都会重新创建包含场景的整个组件树,这会导致控制台中出现大量警告,表明已经创建了具有键“xyz”的场景。
我做了什么:
我使用了react-native-router-flux官方的示例应用,并添加了一个简单的基于redux的反例:
- 一个简单的状态:“计数器”(可能是一个整数)
- reducer 和 action(递增、递减)
下面我将展示一些代码,但也可以找到我的 example application on github, please feel free to check it out: https://github.com/itinance/react-native-router-flux。 "Example" 目录是原始示例应用程序。 "ExampleRedux" 是带有 redux 堆栈和示例 reducer(计数器)的示例的副本,我在这里谈论的是什么。
主应用程序 提供程序和存储的组件:
import * as reducers from './components/reducers';
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
const reducer = combineReducers(reducers);
const store = createStoreWithMiddleware(reducer);
export default class Example extends React.Component {
render() {
return (
<Provider store={store}>
<ExampleContainer/>
</Provider>
);
}
}
我的减速器:
const initialState = {
count: 0
};
export default function counter(state = initialState, action = {}) {
switch (action.type) {
case "INCREMENT":
console.log("do increment", state,
{
...state,
count: state.count + 1
}
);
return {
...state,
count: state.count + 1
};
case "DECREMENT":
return {
...state,
count: state.count - 1
};
default:
return state;
}
}
redux'connect'的内部应用容器:
我将状态和动作传递给场景组件:
<Scene key="launch" component={Launch} title="Launch" initial={true} state={state} {...actions} />
这个ExampleContainer的全部代码:
class ExampleContainer extends React.Component {
constructor(props) {
super(props);
}
render() {
const { state, actions } = this.props;
console.log("Props", this.props, state, actions); // everything ok here
return <Router createReducer={reducerCreate}>
<Scene key="modal" component={Modal} >
<Scene key="root" hideNavBar={true}>
<Scene key="echo" clone component={EchoView} />
<Scene key="register" component={Register} title="Register"/>
<Scene key="home" component={Home} title="Replace" type="replace"/>
<Scene key="launch" component={Launch} title="Launch" initial={true} state={state} {...actions} />
.... lots of other scenes ...
</Scene>
</Scene>
<Scene key="error" component={Error}/>
</Scene>
</Router>;
}
}
export default connect(state => ({
state: state.counter
}),
(dispatch) => ({
actions: bindActionCreators(actions, dispatch)
})
)(ExampleContainer);
这是非常简单的 LaunchScreen,具有简单的计数器功能(以及用于演示路由的示例路由):
class Launch extends React.Component {
constructor(props) {
super(props);
console.log(props);
}
render(){
const { state, increment, decrement } = this.props;
console.log("Props 2: ", this.props, state, increment, decrement);
return (
<View {...this.props} style={styles.container}>
<Text>Launch page</Text>
<Text>{state.count}</Text>
<Button onPress={increment}>Increment</Button>
<Button onPress={()=>Actions.login({data:"Custom data", title:"Custom title" })}>Go to Login page</Button>
<Button onPress={Actions.register}>Go to Register page</Button>
<Button onPress={Actions.register2}>Go to Register page without animation</Button>
<Button onPress={()=>Actions.error("Error message")}>Popup error</Button>
<Button onPress={Actions.tabbar}>Go to TabBar page</Button>
<Button onPress={Actions.pop}>back</Button>
</View>
);
}
}
点击增量按钮时,动作被完美调度。在控制台中,可以成功记录新状态。每次单击它都会一个一个递增。但不在视图中。
当我省略路由器和场景并仅将启动屏幕作为单个组件激活时,一切正常。
问题:
如何使这个 redux 应用程序工作,视图将正确更新它们的状态?
为了完整起见,整个代码可以在github.
上找到您可能忘记将 Launch
组件连接到商店。您想要做的与您在 ExampleContainer
中所做的类似,即
export default connect(state => ({
state: state.counter
}),
(dispatch) => ({
actions: bindActionCreators(actions, dispatch)
})
)(Launch);
然后正确的值将显示在您的日志中