React Native search function not rendering - javascript

I have two functions that are not rendering: renderTeachers() and renderSubjects(). They render based on the length of the teachers array in the state object. I console logged state.teachers and the result is as expected, the array length is more than one, but the functions still don't render. I don't understand why these functions are not rendering.
class Search extends Component {
state = {
teachers: [],
subjects: [],
rating: 3.5,
};
requestData = (queryObj) => {
console.log(queryObj);
const client = algoliasearch('__ID__', '__KEY__');
const queries = [{
indexName: 'teachers',
query: queryObj,
filters: 'Rating >= 3.5',
}, {
indexName: 'subjects',
query: queryObj,
}];
if (queryObj === '') {
this.setState({ showSearchVal: false });
} else {
client.search(queries, this.searchCallback.bind(this));
}
}
searchCallback = (err, content) => {
if (err) {
console.error(err);
return;
}
this.setState({ teachers: content.results[0].hits, subjects: content.results[1].hits });
}
renderSubjects = () => {
if (this.state.subjects.length >= 1) {
return this.state.subjects.map(subject => <SubjectDetail key={subject.objectID} subject={subject} />);
}
return null;
}
renderTeachers = () => {
console.log('in');
if (this.state.teachers.length >= 1) {
return this.state.teachers.map(teacher => <SearchDetail key={teacher.UID} person={teacher} />);
}
return null;
}
render() {
return (
<View>
<Header search onPress={() => this.searchBar.show()} />
<SearchBar
backgroundColor='#02254e'
iconColor='#4f5d6d'
placeholderTextColor='#4f5d6d'
backButton={<Icon name='keyboard-backspace' size={24} color='#4f5d6d' style={{ alignSelf: 'center' }} />}
textColor='white'
animate={false}
handleChangeText={this.requestData}
selectionColor='#01152d'
fontFamily='avenir_heavy'
backCloseSize={24}
ref={(ref) => { this.searchBar = ref; }}
/>
<View style={{ width, height, alignItems: 'center', flex: 1 }}>
<ScrollView style={{ flex: 1 }}>
<Text style={styles.topResultTextStyle}>
{this.state.subjects.length >= 1 ? 'Subjects' : ''}
</Text>
{this.renderSubjects()}
<Text style={styles.topResultTextStyle}>
{this.state.teachers.length >= 1 ? 'Teachers' : ''}
</Text>
{this.renderTeachers()}
</ScrollView>
</View>
</View>
);
}
}
export { Search };

from the code you post, I can't see a reason why teachers / subjects won't render. My question is, how do you set the teachers /subjects arrays ? without changing state / props, react component shouldn't render. Can you please share the arrays set code ?

Related

React Native performance slow

I am new to React Native, I've created an Instagram Clone with customizations, but there got some issues.
FlatList Re-Renderring is slow.
When the like button is Pressed, FlatList is taking 2 Seconds to re-render. So I tried into Flipkart's RecyclerView Package, that is too taking 400-600 ms. I've came to know that Instagram and Facebook are built at React Native, but they don't take this much time on like. I guess something is wrong in my code.
I got Recycler View package from here
Re-Rendering is slow.
In those screens without any List, there is too an issue of slow re-rendering.
Material Top Tabs Navigation is slow.
I've found that React Navigations's Material Top navigation is working absolutely fine on swipe, but on button click, it is taking 2-4 Seconds.
Here is my code for feed page.
import React, { useEffect, useState, useRef } from 'react';
import { SafeAreaView, Pressable, AppRegistry, Text, View, Image, TouchableOpacity, StyleSheet, ImageBackground, ActivityIndicator, Platform } from 'react-native';
import { Pranah } from '../pranah/cust';
import { colors } from '../pranah/colors';
import { uni } from '../css/uni';
import axios from 'axios';
import base64 from 'react-native-base64';
import AsyncStorage from '#react-native-async-storage/async-storage';
import { DataProvider, LayoutProvider, RecyclerListView } from 'recyclerlistview';
import { UserHead } from './tminc/userhead';
import { AntDesign, FontAwesome5, Feather } from '#expo/vector-icons';
import { design } from './tminc/design';
import { WebBasedNavigation } from './tminc/widenav'
const style = StyleSheet.create({
web: {
width: uni.dev("100%", "100%", "40%"),
height: uni.dev("100%", "100%", uni.height - 50),
marginLeft: uni.dev(0, 0, 10 / 100 * uni.width)
}
});
const postDesign = {
width: uni.dev(95 / 100 * uni.width, 95 / 100 * uni.width, 35 / 100 * uni.width),
height: uni.dev(95 / 100 * uni.width, 95 / 100 * uni.width, 35 / 100 * uni.width),
backgroundColor: "#ededed",
borderRadius: 10,
}
const iconDynamicSizing = 25;
const iconDesign = StyleSheet.create({
icon: {
margin: 10
}
});
//POST PART IN PARTS
//USER HEAD
function ListHead(txt) {
return (
<>
<Text
style={{
fontSize: 35,
fontWeight: "bold",
margin: 20
}}
>{txt.txt}</Text>
</>
)
}
function MediaCont(obj) {
return (
<View
style={design.media}
>
<Image
source={{ uri: obj.url }}
defaultSource={{ uri: obj.url }}
style={postDesign}
/>
<View
style={design.mediaSnap}
>
<Text style={design.mediaCap}>{obj.caption.length > 20 ? `${obj.caption.substring(0, 20)}...` : obj.caption}</Text>
</View>
</View>
);
}
function TextCont(obj) {
return (
<View
style={design.textContParent}
>
<View
style={[postDesign, design.center]}
>
<Text
style={design.textMain}
>{obj.caption}</Text>
</View>
</View>
);
}
let layoutProvider = new LayoutProvider(
index => {
return index == 0 ? "HEAD" : "NORMAL";
},
(type, dim) => {
switch (type) {
case "NORMAL":
dim.height = uni.dev(uni.width + 150, uni.width + 150, 40 / 100 * uni.width + 150);
dim.width = uni.dev(uni.width, uni.width, 40 / 100 * uni.width);
break;
case "HEAD":
dim.height = 85;
dim.width = uni.dev(uni.width, uni.width, 40 / 100 * uni.width);
break;
}
}
);
function PostLikes(obj) {
let post = obj.postId;
let like = parseInt(obj.like);
let navigation = obj.screenNav;
let toprint;
if (like == 0) {
toprint = uni.lang("इसे पसंद करने वाले पहले व्यक्ति बनें", "Be first to like this.");
} else if (like == 1) {
toprint = uni.lang("एक व्यक्ति द्वारा पसंद किया गया", "Liked by one person");
} else {
like = String(like);
toprint = uni.lang(`${like} लोगो ने पसंद किया`, `${like} likes`);
}
return (
<>
<TouchableOpacity
onPress={() => {
navigation.push('LikeList', { postId: post });
}}
>
<Text
style={{
marginLeft: uni.dev(5 / 100 * uni.width, 5 / 100 * uni.width, 4 / 100 * uni.width),
fontWeight: "bold",
marginTop: 5
}}
>{toprint}</Text>
</TouchableOpacity>
</>
);
}
const headerComp = ({
title: uni.lang("सबकुछ ||", "Everything."),
type: "head"
});
export function Feed({ navigation }) {
const [List, setData] = useState([headerComp]);
const [FooterConst, setFoot] = useState(true);
const [start, setStart] = useState(0);
// navigation.setOptions({ tabBarVisible: false });
let dataProvider = new DataProvider((r1, r2) => {
return r1 !== r2;
}).cloneWithRows(List);
function fetchMore() {
AsyncStorage.getItem("mail")
.then((val) => {
let mail = val;
AsyncStorage.getItem("pass")
.then((value) => {
let pass = value;
// CONNECTING TO SERVER
axios({
method: 'post',
url: uni.bind('feed'),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: uni.string({
mail: mail,
pass: base64.encode(pass),
start: start
})
})
.then((resp) => {
if (resp.status == 200) {
let page = resp.data;
/*
SERVER RETURNS
nomore | followernull | error | invalid | {json data}
*/
if (uni.logic(page) === "error") {
uni.Error();
} else if (uni.logic(page) === "followernull" || uni.logic(page) === "nomore") {
//SET FOOTER
setFoot(false);
} else if (uni.logic(page) === "invalid") {
//SIGNOUT
uni.signOut(navigation);
} else {
setStart(start + 20);
setData(
[
...List,
...page
]
);
}
} else {
uni.Error();
}
})
.catch((e) => {
uni.Error();
});
})
.catch((e) => { uni.signOut(navigation) })
})
.catch(() => { uni.signOut(navigation) })
}
function PostAction(obj) {
let index = obj.in;
function addRemoveLike() {
let temp = List;
temp[index].liked = temp[index].liked === "true" ? "false" : "true";
// console.warn(temp[index]);
setData([...temp]);
//SAVING LIKE ON SERVER
AsyncStorage.getItem("mail")
.then((val) => {
let mail = val;
AsyncStorage.getItem("pass")
.then((value) => {
let pass = value;
// CONNECTING TO SERVER
axios({
method: 'post',
url: uni.bind('like'),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: uni.string({
mail: mail,
pass: base64.encode(pass),
post: String(obj.id)
})
})
.then((resp) => {
if (resp.status == 200) {
let page = resp.data;
/*
SERVER RETURNS
true | error | invalid
*/
if (uni.logic(page) === "error") {
uni.Error();
} else if (uni.logic(page) === "invalid") {
uni.signOut(navigation);
}
} else {
uni.Error();
}
})
.catch((e) => { uni.Error() });
})
.catch((e) => { uni.signOut(navigation) })
})
.catch(() => { uni.signOut(navigation) })
}
return (
<>
<View
style={design.postActionParent}
>
<TouchableOpacity
onPress={() => {
// console.warn(likeRef.current);
// console.warn(likeRef.current);
addRemoveLike();
}}
><AntDesign name={obj.liked === "true" ? "heart" : "hearto"} size={iconDynamicSizing} color="black" style={iconDesign.icon} /></TouchableOpacity>
<TouchableOpacity onPress={() => {
navigation.push('Comment', { postId: obj.id });
}}><FontAwesome5 name="comment" size={iconDynamicSizing} color="black" style={iconDesign.icon} /></TouchableOpacity>
<TouchableOpacity><Feather name="send" size={iconDynamicSizing} color="black" style={iconDesign.icon} /></TouchableOpacity>
<TouchableOpacity><AntDesign name="retweet" size={iconDynamicSizing} color="black" style={iconDesign.icon} /></TouchableOpacity>
</View>
<View
style={design.underLinePrnt}
>
<View style={design.underline}></View>
</View>
</>
);
}
function TextPost(params) {
let item = params.data;
let index = params.in;
return (
<>
<UserHead dp={item.dp} name={item.name} user={item.username} />
<Pressable onLongPress={() => { alert('null') }}><TextCont caption={item.caption} /></Pressable>
<PostLikes like={item.fav} postId={item.id} screenNav={navigation} />
<PostAction liked={item.liked} in={index} id={item.id} />
</>
);
}
function MediaPost(params) {
let item = params.data;
let index = params.in;
return (
<>
<UserHead dp={item.dp} name={item.name} user={item.username} />
<MediaCont url={item.url} caption={item.caption} />
<PostLikes like={item.fav} postId={item.id} screenNav={navigation} />
<PostAction liked={item.liked} in={index} id={item.id} />
</>
);
}
function ListItem(type, data, index) {
let item = data;
return item.type === "head" ? <ListHead txt={item.title} /> : item.type === "text" ? <TextPost data={item} in={index} /> : <MediaPost data={item} in={index} />;
}
useEffect(function () {
// let tmp = List.push(json);
// setData([
// ...List,
// ...json
// ]);
navigation.setOptions({ tabBarVisible: uni.isPC() == true ? false : true })
fetchMore();
}, []);
function footerComp() {
return FooterConst == true ? (
<>
<ActivityIndicator size={"large"} color={colors.primary} />
<Pranah.br height={20} />
</>) : (
<>
<Text
style={{
textAlign: "center",
width: "100%",
fontSize: 20,
fontWeight: "bold",
paddingBottom: 13
}}
>{uni.lang("सूची का अंत", "End of Posts")}</Text>
</>
);
}
return (
<SafeAreaView style={{ flex: 1, backgroundColor: "#FFFFFF" }}>
<ImageBackground
style={{
width: "100%",
height: "100%"
}}
source={require('../assets/background_mobile.png')}
>
<Pranah.stb />
<Pranah.pranahHead nav={navigation} />
<View
style={{ width: "100%", height: "100%", flexDirection: "row" }}
>
<View
style={style.web}
>
<RecyclerListView
dataProvider={dataProvider}
rowRenderer={ListItem}
layoutProvider={layoutProvider}
extendedState={{ List }}
renderFooter={footerComp}
onEndReached={fetchMore}
/>
</View>
<WebBasedNavigation navigation={navigation} />
</View>
</ImageBackground>
</SafeAreaView>
);
}
There were lags in iOS and Web too but those were acceptable.
I know, I've done very wrong with AsyncStorage, please tell me a short way to do that too.
Thanks in advance.
In your case, I don't know why you are using another package when react-native contains a built-in component called as FlatList which is backed by virtualised rendering.
Make this changes
rowRenderer={() => ListItem()}
renderFooter={() => footerComp()}
Check the () => arrow function this will assign the method only once on the initial render. You need to provide a https://reactnative.dev/docs/flatlist#keyextractor prop to create a unique ID for all the rendered items (will be used when you want to do some action like remove element or update).
With this simple change, you should see a lot of performance improvement for the initial render & for each re-render.
Do the same for the props that accept a function as a param.
IDK why are you storing the value on async storage they should be store in a local variable like the useState hook. Keep an eye on the API call if you do frequent API calls or on each re-render surely it will reduce the app performnce.
My Opinion
React & React Native are fast by default but developers use a lot of anti-pattern code and make the application slow and complain RN is slow.
Here you can find some of the common things which cause performance issues in react native.
https://reactnative.dev/docs/performance

Mapping over sent props using .map react native

i have two components one is called homeScreen the second is card i do fetch data in homeScreen i set it to state after i do send state through props to my card component .
Now my card components should generate 9 cards accoridng to the data i am sending through to it so i did map and i am getting this error
TypeError: Cannot read property '0' of undefined.
i tried to console.log props inside Card component and i could see data but for some reason the map isnt working
Card.js
const Card = props => {
Array.from({length: 9}).map((i, index) => {
console.log(props);
return (
<View style={{flex: 1}}>
<Text style={{flex: 1, backgroundColor: 'red'}}>
{props.title[1] ? `${props.title[index]}` : 'Loading'}
</Text>
<Text style={{flex: 1, backgroundColor: 'blue'}}>{props.rating[index]}</Text>
</View>
);
});
};
export default Card;
homeScreen.js
export default class HomeScreen extends React.Component {
state = {
title: [],
image: [],
rating: [],
isLoading: true,
};
componentDidMount() {
this.getData();
}
titleSend = () => {
if (!this.state.isLoading) {
{
Array.from({length: 9}).map((i, index) => {
return this.state.title[index];
});
}
}
};
imageSetter = () => {
Array.from({length: 9}).map((i, keys) => {
return (
<Image
key={keys}
style={{width: 50, height: 50, flex: 1}}
source={{uri: this.state.image[keys]}}
/>
);
});
};
getData = () => {
const requestUrls = Array.from({length: 9}).map(
(_, idx) => `http://api.tvmaze.com/shows/${idx + 1}`,
);
const handleResponse = data => {
const shows = data.map(show => show.data);
this.setState({
isLoading: false,
title: shows.map(show => show.name),
image: shows.map(show => show.image.medium),
rating: shows.map(show => show.rating.average),
});
// console.log(this.state);
};
const handleError = error => {
this.setState({
isLoading: false,
});
};
Promise.all(requestUrls.map(url => axios.get(url)))
.then(handleResponse)
.catch(handleError);
};
render() {
const {isLoading, title, image, rating} = this.state;
if (isLoading) {
return <ActivityIndicator size="large" color="#0000ff" />;
}
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<ScrollView style={{flex: 1, backgroundColor: 'red'}}>
<Card title={this.state.title} />
</ScrollView>
<Text>here images</Text>
</View>
);
}
}
None of your functions/methods using Array.from are returning a value.
For example your Card component:
const Card = props => {
// note addition of `return` statement
return Array.from({length: 9}).map((i, index) => {
console.log(props);
return (
<View style={{flex: 1}}>
<Text style={{flex: 1, backgroundColor: 'red'}}>
{props.title[1] ? `${props.title[index]}` : 'Loading'}
</Text>
<Text style={{flex: 1, backgroundColor: 'blue'}}>{props.rating[index]}</Text>
</View>
);
});
};
export default Card;
The titleSend and imageSetter methods have a similar issue.
The index error is because you're not passing an rating prop to the Card component but you're accessing props.rating[0], props.rating[1], etc.
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<ScrollView style={{flex: 1, backgroundColor: 'red'}}>
// missing `rating` prop
<Card title={this.state.title} />
</ScrollView>
<Text>here images</Text>
</View>
);

hide a view on condition in react native

I am developing react native application where I wanted to show some loader before loading screen,
I have different component for Loader and different component to load data,
In Loader component I hava a field isVisible (true/false) like below
constructor(props) {
super(props);
this.state = {
index: 0,
types: ['CircleFlip', 'Bounce', 'Wave', 'WanderingCubes', 'Pulse', 'ChasingDots', 'ThreeBounce', 'Circle', '9CubeGrid', 'WordPress', 'FadingCircle', 'FadingCircleAlt', 'Arc', 'ArcAlt'],
size: 100,
color: "#ff0000",
isVisible: true
}
render() {
var type = this.state.types[this.state.index];
return (
<View style={styles.container}>
<Spinner style={styles.spinner} isVisible={this.state.isVisible} size={this.state.size} type={'ThreeBounce'} color={this.state.color}/>
</View>
);
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
// backgroundColor: '#d35400',
},
spinner: {
marginBottom: 50
},
btn: {
marginTop: 20
},
text: {
color: "white"
}
});
and in Other Component where I am rendering my view after getting data from api.
constructor(props) {
super(props);
this.state = {
tableHead: ['Form Name', 'Download'],
tableData: [],
isVisible:true
}
}
componentDidMount(){
dataSourceRes =getDocumentList(function(dataSourceRes){
var tableDataRows=[];
for(let i = 0; i < dataSourceRes.length; i++){
var arr=[];
arr.push(dataSourceRes[i].docName, dataSourceRes[i].docPath);
tableDataRows.push(arr);
}
this.setState({
tableData : tableDataRows
});
}.bind(this));
};
render() {
const state = this.state;
const element = (data, index) => (
<TouchableOpacity onPress={() => this._alertIndex(data)}>
<View style={styles.btn}>
<Text style={styles.btnText}>Download</Text>
</View>
</TouchableOpacity>
);
return (
<View style={styles.container}>
<Loader></Loader>
{/* <Loader> */}
<ScrollView>
<Table borderStyle={{borderColor: 'transparent'}}>
<Row data={state.tableHead} style={styles.head} textStyle={styles.textHeader}/>
{
state.tableData.map((rowData, index) => (
<TableWrapper key={index} style={styles.row}>
{
rowData.map((cellData, cellIndex) => (
<Cell key={cellIndex} data={cellIndex === 1 ? element(cellData, index) : cellData} textStyle={styles.text}/>
))
}
</TableWrapper>
))
}
</Table>
</ScrollView>
{/* </Loader> */}
</View>
)
}
}
Please let me know the solution how to resolve it
You could do as follows
class Foo extends React.Component {
constructor(props) {
this.state = { loading: true };
}
componentDidMount() {
// Fetch data then set state
fetch(something).then(() => this.setState({ loading: false }));
}
render() {
if (this.state.loading) {
return <Loader/>;
}
return <MyComponent/>;
}
}
After fetched data from api then send isvisibility false to loader component

Update Listview which contains Row and Section

I have 2 components which are CalendarList and CalendarListItem. I use Listview to displays 10 records in CalendarListItem at the first load and it will add more 10 records when user scroll down.
I meet trouble when try to update Listview containing Row and Section to append next 10 records when user scroll down to the end of list. I have searched and applied hints but most of questions relating with rows only that not work for me.
Here is my code:
constructor(props) {
super(props);
this.ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
sectionHeaderHasChanged: (s1, s2) => s1 !== s2,
});
this.state = {
eventData: [],
eventDatas: [],
dataBlob: {},
dataSource: {},
dataBlog: [],
refreshing: false,
page: 1
};
}
componentWillMount() {
this.loadEventData();
}
componentDidMount() {
this.loadEventData();
}
loadEventData() {
eventState = this.props.eventtop;
console.log('NEW DATA', eventState);
const tempDataBlob = this.state.dataBlob;
this.state.eventData = this.props.eventtop;
this.state.eventData.forEach(item => {
const event = item;
const date = new Date(item.EventDate);
const group = dateFormat(date, 'mmmm yyyy');
if (currentGroup !== group) {
currentGroup = group;
currentIndex++;
this.state.eventDatas.push({ divider: currentGroup, data: [] });
}
this.state.eventDatas[currentIndex].data.push(event);
tempDataBlob[this.state.eventDatas[currentIndex].divider] = this.state.eventDatas[currentIndex].data;
this.setState({
dataBlob: tempDataBlob
});
});
this.setState({
dataSource: this.ds.cloneWithRowsAndSections(this.state.dataBlob)
});
console.log('FUCKING DATA', this.state.dataBlob);
}
renderRow(rowData) {
return (
<TouchableOpacity
onPress={() => {
if (window.width <= 600) {
Actions.calendarDetail({ eventtop: rowData });
} else if (window.width > 600) {
this.props.getEventd(rowData);
this.passState.bind(this.props.eventItems);
}
}}
>
<View>
<Text style={styles.evenType}>
{rowData.EventType}
</Text>
<Text style={{ ...styles.contentStyle, ...styles.contenStyle2 }}>
{dateFormat(rowData.EventDate, 'mm/dd/yyyy')}
</Text>
<Icon
name='chevron-thin-right'
style={styles.iconStyle}
/>
<View
style={styles.titleStyle}
>
<Text style={styles.contentStyle}>
{rowData.Title}
</Text>
</View>
</View>
</TouchableOpacity>
);
}
renderSectionHeader(sectionData, sectionId) {
return (
<View>
<Text style={styles.timeStyle}>
{sectionId}
</Text>
</View>
);
}
render() {
return (
<ListView
style={{ flex: 1 }}
enableEmptySections
dataSource={this.state.dataSource}
renderRow={data => this.renderRow(data)}
renderSectionHeader={this.renderSectionHeader}
onEndReached={this.props.onEndReached}
renderFooter={this.props.renderFooter}
onEndReachedThreshold={30}
/>
);
}
I found a solution yesterday. Actually I need to create another Action Creator and place it inside CalendarListItem, that action will return state which is new data then I concat old data with that new data. Done!

React Native Android change scene navigator

I'm trying to build a tabview and I can't find out how to change and render scenes. My main view is this one (App.js) :
<View style={{flex: 1}}>
<TabView
ref="tabs"
onTab={(tab) => {
this.setState({tab});
}}
tabs={[
{
component: List,
name: 'Découvrir',
icon: require('../assets/img/tabs/icons/home.png')
},
{
component: Friends,
name: 'Amis',
icon: require('../assets/img/tabs/icons/friend.png'),
pastille: this.state.friendsPastille < 10 ? this.state.friendsPastille : '9+'
},
{
component: RecoStep1,
icon: require('../assets/img/tabs/icons/add.png'),
hasShared: MeStore.getState().me.HAS_SHARED
},
{
component: Notifs,
name: 'Notifs',
icon: require('../assets/img/tabs/icons/notif.png'),
pastille: this.state.notifsPastille < 10 ? this.state.notifsPastille : '9+'
},
{
component: Profil,
name: 'Profil',
icon: require('../assets/img/tabs/icons/account.png')
}
]}
initialSkipCache={!!this.notifLaunchTab}
initialSelected={this.notifLaunchTab || 0}
tabsBlocked={false} />
</View>
The TabView component is this one and it works fine. Only the navigator renders a blank screen only...
renderTab(index, name, icon, pastille, hasShared) {
var opacityStyle = {opacity: index === this.state.selected ? 1 : 0.3};
return (
<TouchableWithoutFeedback key={index} style={styles.tabbarTab} onPress={() => {
if (this.props.tabsBlocked) {
return;
}
this.resetToTab(index);
}}>
<View style={styles.tabbarTab}>
<Image source={icon} style={opacityStyle} />
{name ?
<Text style={[styles.tabbarTabText, opacityStyle]}>{name}</Text>
: null}
</View>
</TouchableWithoutFeedback>
);
}
resetToTab(index, opts) {
this.setState({selected: index});
}
renderScene = (route, navigator) => {
var temp = navigator.getCurrentRoutes();
return temp[this.state.selected].component;
}
render() {
return (
<View style={styles.tabbarContainer}>
<Navigator
style={{backgroundColor: '#FFFFFF', paddingTop: 20}}
initialRouteStack={this.props.tabs}
initialRoute={this.props.tabs[this.props.initialSelected || 0]}
ref="tabs"
key="navigator"
renderScene={this.renderScene}
configureScene={() => {
return {
...Navigator.SceneConfigs.FadeAndroid,
defaultTransitionVelocity: 10000,
gestures: {}
};
}} />
{this.state.showTabBar ? [
<View key="tabBar" style={styles.tabbarTabs}>
{_.map(this.props.tabs, (tab, index) => {
return this.renderTab(index, tab.name, tab.icon, tab.pastille, tab.hasShared);
})}
</View>
] : []}
</View>
);
}
I know I'm doing something wrong, but I can't figure out what ... Changing tabs doesn't display anything as shown below..
I used NavigatorIOS for ans iOS version that worked fine with the following navigator in the render method in TabView (I don't know how to go from the NavigatorIOS to Navigator) :
<Navigator
style={{backgroundColor: '#FFFFFF', paddingTop: 20}}
initialRouteStack={this.props.tabs}
initialRoute={this.props.tabs[this.props.initialSelected || 0]}
ref="tabs"
key="navigator"
renderScene={(tab, navigator) => {
var index = navigator.getCurrentRoutes().indexOf(tab);
return (
<NavigatorIOS
style={styles.tabbarContent}
key={index}
itemWrapperStyle={styles.tabbarContentWrapper}
initialRoute={tab.component.route()}
initialSkipCache={this.props.initialSkipCache} />
);
}}
configureScene={() => {
return {
...Navigator.SceneConfigs.FadeAndroid,
defaultTransitionVelocity: 10000,
gestures: {}
};
}} />
Try adding a
flex:1
property to the navigator. If that doesn't work, check to see that the tabbarContainer also has a
flex:1
property.
OK, I found the answer : I changed my renderScene method to the following :
renderScene = (route, navigator) => {
var temp = navigator.getCurrentRoutes();
return React.createElement(temp[this.state.selected].component, _.extend({navigator: navigator}, route.passProps));
}
Works fine now.

Categories

Resources