道具更新时重新渲染组件(使用 Redux)

Posted

技术标签:

【中文标题】道具更新时重新渲染组件(使用 Redux)【英文标题】:Re render Component when props updates (w/ Redux) 【发布时间】:2018-01-30 05:01:37 【问题描述】:

好的,所以我有 2 个组件,地图和应用程序。 App 组件基本上保存了地图。

这是我的应用程序的代码:

import React,  Component  from 'react';
import  Text, View  from 'react-native';

import  StackNavigator, TabNavigator  from 'react-navigation';
//Redux
import  Provider  from 'react-redux';
import  createStore, applyMiddleware  from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

//Screen Imports
import CenterNew from './screens/CenterNew';
import Map from './components/Map';
import Profile from './containers/Profile';
import Review from './containers/Review';

import  connect  from 'react-redux';

var store = createStore(rootReducer, , applyMiddleware(thunk));

class App extends Component 
	
	render () 
		
		 console.ignoredYellowBox = ['Remote debugger']; 

		const MainScreenNavigator = TabNavigator(
		  Centers: screen: Map,
		  Review: screen: Review,
		  Profile: screen: Profile
		);

		MainScreenNavigator.navigationOptions = 
		  title: this.props.map.title
		;

		const Screens = StackNavigator(
		  Home: screen: MainScreenNavigator,
		  CenterNew: screen: CenterNew
		);


		return (
			<Provider store=store>
	    	  <Screens />
	    	</Provider>
    	);
	


const connectWithStore = (store, WrappedComponent, mapStateToProps) => 
  let ConnectedWrappedComponent = connect(mapStateToProps)(WrappedComponent);
  return (props) => 
    return <ConnectedWrappedComponent ...props store=store />
  


const mapStateToProps = (state) => 
	return 
		map: state.map
	;
;

App = connectWithStore(createStore(rootReducer, , applyMiddleware(thunk)), App, mapStateToProps);

export default App;

在 sn-p 中,我使用 MainScreenNavigator.navigationOptions = title: this.props.map.title ;

因此,每当呈现 App 时,我都会记录初始状态,正如您在 componentWillMount() 中看到的那样,这就是结果。一个syou可以看到,初始标题是'Home'

现在,在我的地图中,我有一个按钮可以触发此操作创建者,只是为了更改标题文本:

this.props.changeHeaderTitle('Test');
console.log(this.props.map);

代码:

export const changeHeaderTitle = (title) => 
return 
    type: 'CHANGE_HEADER_TITLE',
    payload: title
;

;

这是我的减速器:

const INITIAL_STATE = 
	isPinnable: false,
	pinnedCoordinateLatitude: 0,
	pinnedCoordinateLongitude: 0,
	region: 
	    latitude: 14.582524,
	    longitude: 121.061547,
	    latitudeDelta: 0.007,
	    longitudeDelta: 0.007
	,
	title: '',
	searched: false
;

export default (state = INITIAL_STATE, action) => 
	switch(action.type) 
		case 'ENABLE_PINNING':
			return  ... state, isPinnable: true 
		case 'DISABLE_PINNING':
			return  ... state, isPinnable: false,
				pinnedCoordinateLatitude: action.payload.latitude,
				pinnedCoordinateLongitude: action.payload.longitude 
		case 'GET_PINNED_COORDINATE':
			let test = action.payload.longitude;

			return  
				...state, 
				isPinnable: false,
				pinnedCoordinateLatitude: action.payload.latitude,
				pinnedCoordinateLongitude: action.payload.longitude
			
		case 'GET_CURRENT_REGION':
			return  ...state, region: region 
		case 'CHANGE_CURRENT_REGION':
			return  ...state, region: action.payload
		case 'CHANGE_HEADER_TITLE':
			return  ...state, title: action.payload 
		case 'SEARCHED_VIEW':
			return  ...state, searched: action.payload 
		default:
			return state;
	
;

每当触发操作时,我都知道标题已更新,因为我记录了它,正如您在

中看到的那样
this.props.changeHeaderTitle('Test');

console.log(this.props.map);

但在我看来,标题仍然是“主页”。我提到了这个:rerender react component when prop changes 并尝试使用componentWillRecieveProps(),但是当从地图组件触发this.props.changeHeaderTitle('Test'); 操作时它没有记录。

【问题讨论】:

展示你的减速器。如果状态正在改变,但你的组件没有更新,这通常是因为你改变了状态对象而不是返回一个新的对象。请参阅redux.js.org/docs/basics/Reducers.html -> “我们不会改变状态。我们使用 Object.assign() 创建一个副本” 我更新了我的帖子..我认为我没有改变状态,因为我使用了传播运算符?.. 【参考方案1】:

您需要将 Redux 存储与组件连接起来。因此你应该添加这个sn-p:

mapStateToProps(store)
    const  title  = store; 
    return  title ; 
    
export default connect(mapStateToProps,  changeHeaderTitle )(App) 

mapStateToProps 函数将订阅 redux 存储更新。每次你的状态改变时,你的组件都会自动重新渲染。您可以在此处找到有关将组件连接到 redux 存储的更多信息:react-redux api docs

【讨论】:

我已经更新了我的代码 sn-p 以包含我的完整代码.. 它已经订阅了 redux 我认为您忘记将动作创建者“changeHeaderTitle”注入到连接方法中,就像我在上面的示例中所做的那样。这就是为什么你的状态不会改变。 在 Map 组件中调用了“changeHeaderTitle”动作创建者。 App 组件仅通过道具接收“更新”“更新”状态.. 所以我认为我不需要注入 changeHeaderTitle() 动作创建者,因为我只在地图组件中使用它...【参考方案2】:

您无法像在您提供的代码中那样更新屏幕标题。

 //This is only needed if you want to set the title from another screen

 static navigationOptions = ( navigation ) =>  
const state = navigation;
 return  title: `$state.params.title`, 
; 
; 
ChangeThisTitle = (titleText) =>  
const setParams = this.props.navigation; setParams( title: titleText ) 
 

//Your render method
render()
//Views goes here
 

要更改标题,您可以从 onPress 调用更改标题方法。

您可以参考link了解更多详情。

【讨论】:

我正在嵌套导航器。所以我目前使用这个MainScreenNavigator.navigationOptions = title: 'My Chats', ; 来更改标题.. 我在这里得到它:reactnavigation.org/docs/intro/nesting

以上是关于道具更新时重新渲染组件(使用 Redux)的主要内容,如果未能解决你的问题,请参考以下文章

高阶组件状态正在正确更新,但接收道具的包装组件不会在状态更改时重新渲染

当父组件在 Next.js 应用程序中更新其道具时重新渲染 React 子组件

React Native 和 Redux:为啥子组件不会在每次状态更新时重新渲染?

将新的商店状态放入道具后,反应不会重新渲染

防止子级在更新父级状态时重新渲染,使用父级方法作为本机反应的道具

React Redux Store 更新,但组件不重新渲染