使用componentWillMount/UnMount时遇Provider无法动态修改store错误求助
Hey, let's figure out why you're hitting that Redux Provider error when using those lifecycle methods.
First, let's break down the root causes:
- You're creating a new Redux Store on every render: Your
rendermethod callscreateStore(reducers)inside the Provider every time the component re-renders (like when your network state changes). React Redux's Provider doesn't allow swapping out the store dynamically after it's mounted, which triggers that error when lifecycle methods likecomponentWillUnmountrun. - Typo in lifecycle method name: You wrote
componentWillUnMount(capital M at the end), but the correct name iscomponentWillUnmount(lowercase m). This means your event listener never gets removed, which can cause memory leaks on top of the store issue.
Here's how to fix it step by step:
Step 1: Create your Redux Store once, outside the component
Instead of making a new store every render, create it once when your app loads. You can do this either outside the App component, or in the constructor so it's only initialized once.
Step 2: Fix the lifecycle method spelling
Make sure componentWillUnmount is spelled correctly so your event listener is properly cleaned up.
Step 3: Clean up the network listener logic
Ensure you're properly removing the listener when the component unmounts, now that the lifecycle method is correctly named.
Here's your updated code with all these fixes:
import React, { Component } from 'react'; import { View, NetInfo, Image } from 'react-native'; import { Container, Text } from 'native-base'; import { RootNavigator } from './src/root'; import { Provider } from 'react-redux'; import { createStore } from 'redux'; import reducers from './src/reducers/index'; // Create the store ONCE, outside the component const store = createStore(reducers); export default class App extends Component { constructor(props){ super(props); this.state={ connection: null, }; // Bind the handler to preserve context this.handleConnectionChange = this.handleConnectionChange.bind(this); } componentWillMount(){ NetInfo.isConnected.addEventListener("connectionChange", this.handleConnectionChange); NetInfo.isConnected.fetch().done((isConnected) => this.setState({connection: isConnected})); } // Fixed spelling: componentWillUnmount (lowercase m) componentWillUnmount(){ NetInfo.isConnected.removeEventListener("connectionChange", this.handleConnectionChange); } handleConnectionChange(isConnected){ this.setState({connection: isConnected}); } handeView(){ if(this.state.connection !== null && this.state.connection){ return <RootNavigator /> } else { return ( <View style={{flex:1, flexDirection:"row", alignItems:"center", justifyContent:"center"}}> <Image source={require("./images/connection.gif")} style={{height: 150, width: 150, resizeMode : "stretch"}} /> </View> ); } } render() { return ( // Use the pre-created store instead of making a new one <Provider store={store}> <Container> {this.handeView()} </Container> </Provider> ); } }
Bonus: Notes for future reference
- If you ever need to update your reducers (like for hot reloading), you can use
store.replaceReducer(newReducers)instead of creating a new store. This keeps the same store instance but swaps out the reducer logic, which is allowed. - For newer React Native projects, consider using functional components with
useEffectinstead of class lifecycle methods—it's the recommended approach now, and handles cleanup more intuitively with return functions.
内容的提问来源于stack exchange,提问作者Amir Hossein
相关产品推荐
相关产品推荐

