每次我导航离开并返回屏幕时,Redux 或 RNRF 递增渲染 3-4
Redux or RNRF incrementing renders by 3-4 every-time i navigate away and comeback to screen
我认为这可能是一个 redux 问题,但我开始怀疑这是否与导航堆栈有关..
我正在尝试通过 firebase 加载与不同人的一些聊天。首次加载时,一切正常。但是,如果我点击聊天,发送一个 'text' 到 firebase 并导航回聊天列表屏幕,我注意到在控制台中,每次我离开然后回来时,屏幕都会被渲染 3-4 次背部。来回运行一段时间后,屏幕可能会在完成前渲染 50 次。显然对 UI.
有很大的拖累
在这种情况下,我可以使用下拉刷新进行重现。它应该在更改时更新 UI 并渲染 2-3 次,或者通过减速器中的匹配不执行任何操作。但它几乎总是在 ~3-4
的渲染中递增
我花了好几个小时弄乱 redux 看看我是否做错了什么,但我想知道从 Firebase 返回的新数据是否正在更新堆栈中的每个视图?
我尝试使用 Actions.reset('scene') 方法,但如果我将其用作收件箱的入口点,则会引发错误。我什至在我的路由器场景中尝试过 type=ActionsConst.RESET 但它似乎不再有效(仅替换)。
我现在很茫然。任何帮助将不胜感激。
RN:0.58.5
RNRF:4.0.6
React-Redux:6.0.1
Messages.js
class Messages extends Component {
constructor(props){
super(props);
console.log(props);
}
async componentDidMount() {
console.log('messages mounted');
const user_id = this.props.user_id;
await this.props.getFBKeys({ promoter_id });
await this.openFirebase();
}
componentWillUnmount() {
console.log('inbox unmounted');
}
openFirebase(){
console.log('starting openFirebase');
let dataArr = [];
let counter = 0;
for (let i = 0; i < this.props.firebaseKeys.length; i++) {
ref.child(`/${this.props.firebaseKeys[i]}`).once("value", (snapshot) => {
const snapshotKey = snapshot.key;
const snapshotVal = snapshot.val();
const data = { [snapshotKey] : snapshotVal };
dataArr.push(data);
counter++;
if (counter === this.props.firebaseKeys.length){
this.props.getListOfChats({dataArr});
console.log("setting state");
}
});
}
}
_onRefresh = () => {
Actions.Inbox({type: ActionConst.RESET});
// also tried Actions.reset('Inbox'); & Actions.reset({sceneKey: 'Inbox', index: 0});
this.openFirebase();
};
renderDataOrErrorState(){
if (this.props.loadingData){
console.log('hit 1');
return <Spinner/>;
} else {
if (!this.props.listOfChats){
console.log('hit 2');
return <ErrorComponent errorText='You dont have any messages' iconSize={140}/>
} else {
console.log('hit 3');
return (
<FlatList
data={this.props.listOfChats}
// extraData={this.state.chatThread}
renderItem={({item}) => <MessagePreview item={item}/>}
keyExtractor={(item, index) => 'key'+index}
/>
)
}
}
}
render() {
console.count(' MESSAGES counter');
return (
<View style={styles.container}>
<StandardToolbar titleText="INBOX"/>
<ScrollView
refreshControl={
<RefreshControl
refreshing={false}
onRefresh={this._onRefresh}
/>
}
>
{this.renderDataOrErrorState()}
</ScrollView>
</View>
)
}
}
const styles = {
container: {
flex: 1,
backgroundColor: '#fff',
},
spaceBetween: {
margin: 10
},
marginBottom: {
marginBottom: 70
}
};
const mapStateToProps = ({ loggedInUser, messagesReducer }) => {
const { firebaseKeys, loadingData, listOfChats} = messagesReducer;
const { user_id } = loggedInUser;
return { firebaseKeys, promoter_id, loadingData, listOfChats };
};
export default connect(mapStateToProps, {
getFBKeys,
getListOfChats,
updateListOfChats
})(Messages);
MessagesActions.js
import {
MAIN_BASE_URL,
GET_FIREBASE_KEYS,
NO_FIREBASE_KEYS,
GET_LIST_OF_CHATS,
UPDATE_LIST_OF_CHATS,
UPDATE_FALSE
} from "../../actions/types";
import axios from 'axios';
export const getFBKeys = ({ user_id }) => {
return (dispatch) => {
return axios.get(`Main/Url/To/Get/Data`, {
params: {
user_id: user_id,
}
}).then((response) => {
// console.log(response.data.length);
if (response.data.length === 0){
dispatch({type: NO_FIREBASE_KEYS });
} else {
dispatch({type: GET_FIREBASE_KEYS, payload: response.data });
}
}).catch((error) => {
console.log(JSON.stringify(error));
})
}
};
export const getListOfChats = ({dataArr}) => {
return (dispatch) => {
dispatch({
type: GET_LIST_OF_CHATS,
payload: dataArr
});
}
};
MessagesReducer.js
import {
GET_FIREBASE_KEYS,
NO_FIREBASE_KEYS,
GET_LIST_OF_CHATS,
} from "../../actions/types";
import _ from 'lodash';
const INITIAL_STATE = {
listOfChats: [],
firebaseKeys: [],
loadingData: true,
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case GET_FIREBASE_KEYS:
if (JSON.stringify(action.payload) === JSON.stringify(state.firebaseKeys)){
return Object.assign({}, state);
} else {
return Object.assign({}, state, {
firebaseKeys: action.payload,
loadingData: false
});
}
case NO_FIREBASE_KEYS:
return Object.assign({}, state, {
loadingData: false
});
case GET_LIST_OF_CHATS:
if (_.isEqual(action.payload, state.listOfChats)){
console.log('chat state equal. returning state');
return Object.assign({}, state);
} else {
console.log('returning new chats');
return Object.assign({}, state, {
loadingData: false,
listOfChats: action.payload
});
}
default:
return state;
}
}
Router.js
<Router>
<Scene key='root' hideNavBar={true}>
{/* Controls main TabBar */}
<Tabs
key="TabBar"
tabBarPosition="bottom"
tabBarComponent={TabBar}
>
<Scene
key='Home'
hideNavBar={true}
initial
>
<Scene
key='Main'
hideNavBar={true}
initial
>
<Scene
key='homeScreen'
hideNavBar={true}
component={HomeScreen}
title='Home'
initial
/>
<Scene
key='CustomerProfile'
hideNavBar={true}
component={CustomerProfile}
title='Customer Profile'
/>
<Scene
key='CustomerSearch'
hideNavBar={true}
component={CustomerSearch}
title='Customer Search'
/>
<Scene
key='WriteAReview'
hideNavBar={true}
component={WriteAReview}
title='Write A Review'
/>
<Scene
key='ReviewsHome'
hideNavBar={true}
component={ReviewsHome}
title='Reviews'
/>
</Scene>
<Scene
key="Camera"
component={Scanner}
title="QRCodeScanner"
hideNavBar={true}
hideTabBar={true}
/>
<Scene
key='Inbox'
component={Messages}
title='Inbox'
hideNavBar={true}
// tried this as well --> type={ActionsConst.RESET}
/>
<Scene
key='Text'
component={FullText}
title='Text'
hideNavBar={true}
hideTabBar={true}
// type='replace'
/>
<Scene
key='GL'
component={GL}
title='GL'
hideNavBar={true}
/>
<Scene
key='STA'
component={STA}
title='Your STA'
hideNavBar={true}
/>
<Scene
key="PubProf"
hideNavBar={true}
>
<Scene
key="Profile"
component={Profile}
title="Profile"
hideNavBar={true}
initial
/>
<Scene
key='PublicProfile'
component={PublicProfile}
title='Public Profile'
hideNavBar={false}
/>
</Scene>
</Scene>
</Tabs>
</Scene>
</Router>
天哪,我想通了。出于一些愚蠢的原因,我将标签栏中的所有场景都包裹在一个名为 'Home' 的父场景中。删除它会停止所有不必要的渲染。赞美主
我认为这可能是一个 redux 问题,但我开始怀疑这是否与导航堆栈有关..
我正在尝试通过 firebase 加载与不同人的一些聊天。首次加载时,一切正常。但是,如果我点击聊天,发送一个 'text' 到 firebase 并导航回聊天列表屏幕,我注意到在控制台中,每次我离开然后回来时,屏幕都会被渲染 3-4 次背部。来回运行一段时间后,屏幕可能会在完成前渲染 50 次。显然对 UI.
有很大的拖累在这种情况下,我可以使用下拉刷新进行重现。它应该在更改时更新 UI 并渲染 2-3 次,或者通过减速器中的匹配不执行任何操作。但它几乎总是在 ~3-4
的渲染中递增我花了好几个小时弄乱 redux 看看我是否做错了什么,但我想知道从 Firebase 返回的新数据是否正在更新堆栈中的每个视图?
我尝试使用 Actions.reset('scene') 方法,但如果我将其用作收件箱的入口点,则会引发错误。我什至在我的路由器场景中尝试过 type=ActionsConst.RESET 但它似乎不再有效(仅替换)。
我现在很茫然。任何帮助将不胜感激。
RN:0.58.5 RNRF:4.0.6 React-Redux:6.0.1
Messages.js
class Messages extends Component {
constructor(props){
super(props);
console.log(props);
}
async componentDidMount() {
console.log('messages mounted');
const user_id = this.props.user_id;
await this.props.getFBKeys({ promoter_id });
await this.openFirebase();
}
componentWillUnmount() {
console.log('inbox unmounted');
}
openFirebase(){
console.log('starting openFirebase');
let dataArr = [];
let counter = 0;
for (let i = 0; i < this.props.firebaseKeys.length; i++) {
ref.child(`/${this.props.firebaseKeys[i]}`).once("value", (snapshot) => {
const snapshotKey = snapshot.key;
const snapshotVal = snapshot.val();
const data = { [snapshotKey] : snapshotVal };
dataArr.push(data);
counter++;
if (counter === this.props.firebaseKeys.length){
this.props.getListOfChats({dataArr});
console.log("setting state");
}
});
}
}
_onRefresh = () => {
Actions.Inbox({type: ActionConst.RESET});
// also tried Actions.reset('Inbox'); & Actions.reset({sceneKey: 'Inbox', index: 0});
this.openFirebase();
};
renderDataOrErrorState(){
if (this.props.loadingData){
console.log('hit 1');
return <Spinner/>;
} else {
if (!this.props.listOfChats){
console.log('hit 2');
return <ErrorComponent errorText='You dont have any messages' iconSize={140}/>
} else {
console.log('hit 3');
return (
<FlatList
data={this.props.listOfChats}
// extraData={this.state.chatThread}
renderItem={({item}) => <MessagePreview item={item}/>}
keyExtractor={(item, index) => 'key'+index}
/>
)
}
}
}
render() {
console.count(' MESSAGES counter');
return (
<View style={styles.container}>
<StandardToolbar titleText="INBOX"/>
<ScrollView
refreshControl={
<RefreshControl
refreshing={false}
onRefresh={this._onRefresh}
/>
}
>
{this.renderDataOrErrorState()}
</ScrollView>
</View>
)
}
}
const styles = {
container: {
flex: 1,
backgroundColor: '#fff',
},
spaceBetween: {
margin: 10
},
marginBottom: {
marginBottom: 70
}
};
const mapStateToProps = ({ loggedInUser, messagesReducer }) => {
const { firebaseKeys, loadingData, listOfChats} = messagesReducer;
const { user_id } = loggedInUser;
return { firebaseKeys, promoter_id, loadingData, listOfChats };
};
export default connect(mapStateToProps, {
getFBKeys,
getListOfChats,
updateListOfChats
})(Messages);
MessagesActions.js
import {
MAIN_BASE_URL,
GET_FIREBASE_KEYS,
NO_FIREBASE_KEYS,
GET_LIST_OF_CHATS,
UPDATE_LIST_OF_CHATS,
UPDATE_FALSE
} from "../../actions/types";
import axios from 'axios';
export const getFBKeys = ({ user_id }) => {
return (dispatch) => {
return axios.get(`Main/Url/To/Get/Data`, {
params: {
user_id: user_id,
}
}).then((response) => {
// console.log(response.data.length);
if (response.data.length === 0){
dispatch({type: NO_FIREBASE_KEYS });
} else {
dispatch({type: GET_FIREBASE_KEYS, payload: response.data });
}
}).catch((error) => {
console.log(JSON.stringify(error));
})
}
};
export const getListOfChats = ({dataArr}) => {
return (dispatch) => {
dispatch({
type: GET_LIST_OF_CHATS,
payload: dataArr
});
}
};
MessagesReducer.js
import {
GET_FIREBASE_KEYS,
NO_FIREBASE_KEYS,
GET_LIST_OF_CHATS,
} from "../../actions/types";
import _ from 'lodash';
const INITIAL_STATE = {
listOfChats: [],
firebaseKeys: [],
loadingData: true,
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case GET_FIREBASE_KEYS:
if (JSON.stringify(action.payload) === JSON.stringify(state.firebaseKeys)){
return Object.assign({}, state);
} else {
return Object.assign({}, state, {
firebaseKeys: action.payload,
loadingData: false
});
}
case NO_FIREBASE_KEYS:
return Object.assign({}, state, {
loadingData: false
});
case GET_LIST_OF_CHATS:
if (_.isEqual(action.payload, state.listOfChats)){
console.log('chat state equal. returning state');
return Object.assign({}, state);
} else {
console.log('returning new chats');
return Object.assign({}, state, {
loadingData: false,
listOfChats: action.payload
});
}
default:
return state;
}
}
Router.js
<Router>
<Scene key='root' hideNavBar={true}>
{/* Controls main TabBar */}
<Tabs
key="TabBar"
tabBarPosition="bottom"
tabBarComponent={TabBar}
>
<Scene
key='Home'
hideNavBar={true}
initial
>
<Scene
key='Main'
hideNavBar={true}
initial
>
<Scene
key='homeScreen'
hideNavBar={true}
component={HomeScreen}
title='Home'
initial
/>
<Scene
key='CustomerProfile'
hideNavBar={true}
component={CustomerProfile}
title='Customer Profile'
/>
<Scene
key='CustomerSearch'
hideNavBar={true}
component={CustomerSearch}
title='Customer Search'
/>
<Scene
key='WriteAReview'
hideNavBar={true}
component={WriteAReview}
title='Write A Review'
/>
<Scene
key='ReviewsHome'
hideNavBar={true}
component={ReviewsHome}
title='Reviews'
/>
</Scene>
<Scene
key="Camera"
component={Scanner}
title="QRCodeScanner"
hideNavBar={true}
hideTabBar={true}
/>
<Scene
key='Inbox'
component={Messages}
title='Inbox'
hideNavBar={true}
// tried this as well --> type={ActionsConst.RESET}
/>
<Scene
key='Text'
component={FullText}
title='Text'
hideNavBar={true}
hideTabBar={true}
// type='replace'
/>
<Scene
key='GL'
component={GL}
title='GL'
hideNavBar={true}
/>
<Scene
key='STA'
component={STA}
title='Your STA'
hideNavBar={true}
/>
<Scene
key="PubProf"
hideNavBar={true}
>
<Scene
key="Profile"
component={Profile}
title="Profile"
hideNavBar={true}
initial
/>
<Scene
key='PublicProfile'
component={PublicProfile}
title='Public Profile'
hideNavBar={false}
/>
</Scene>
</Scene>
</Tabs>
</Scene>
</Router>
天哪,我想通了。出于一些愚蠢的原因,我将标签栏中的所有场景都包裹在一个名为 'Home' 的父场景中。删除它会停止所有不必要的渲染。赞美主