how do I dynamically render title as component - reactjs

I have a scene:
<Scene key="myFeed" component={myFeed} renderTitle={level}/>
In which I use the component to display the "title".
This function:
const level = () => {
return (
<Level/>
)
}
This component:
export class Level extends Component {
constructor(props) {
super(props);
this.state = {
progressBar: {},
loading: true,
};
}
connection() {
myApi.getServer('/user/level/', (data) => {
this.setState({loading: false, progressBar: data});
}, (err) => {
console.log(err.message);
this.setState({loading: false});
})
}
render() {
return(
<View style={styles.topBarCenterSlider}>
<View style={styles.topBarSlider}>
<View style={[styles.topBarStatus, {width: this.state.progressBar.level["progress"] + '%' : 0}]}/>
</View>
</View>
</View>
);
}
}
I need to change the component after the server response.
Help please, and sorry for my English))

I see you dont invoke "connection()". Put in componentWiLlMount
componentWillMount() {
this.connection();
}

Related

AsyncStorage React Native Session

When I run my application, if I have session data in AsyncStorage, I load it, but it's being loaded after the component mounts and sent to mainContainer as undefined, I need to first load the data and then send it to MainContainer
export default class AppContainer extends Component<{}> {
constructor(props) {
super(props);
this.state = {
data: this.props.data,
authtoken: this.props.authtoken,
sucursal: this.props.sucursal
};
}
componentWillMount() {
if(AsyncStorage.getItem('authtoken') !== null){
this.getDataFromStorage();
}
}
async getDataFromStorage() {
AsyncStorage.getItem('authtoken').then((token) => {
this.setState({ authtoken: token });
console.log(this.state.authtoken);
});
AsyncStorage.getItem('data').then((dataStorage) => {
this.setState({ data: JSON.parse(dataStorage) });
console.log(this.state.data);
});
}
componentDidMount() {
console.log(this.state.data);
console.log(this.state.authtoken);
}
render(props) {
return (
<View style={styles.bigContainer}>
<Header/>
<MainContainer data={this.state.data} authtoken={this.state.authtoken} sucursal={this.state.sucursal}/>
</View>
);
}
}
Introduce Loading Indicator to your component tree. Check for the value of this.state.data. Stop the indicator only once you render data.
render(props) {
return (
<View style={styles.bigContainer}>
<ActivityIndicator animating={!this.state.data} size="large" color="#0000ff" />
<Header/>
<MainContainer data={this.state.data} authtoken={this.state.authtoken} sucursal={this.state.sucursal}/>
</View>
);
}
You might have to change the styling.

getting 'Invariant Violation: `refreshing` prop must be set as a boolean in order to use `onRefresh`, but got `undefined`'

When the home screen loads I get 'Invariant Violation: refreshing prop must be set as a boolean in order to use onRefresh, but got undefined' please help.
class Home extends Component {
constructor(props) {
super(props)
this.state = {
suggestionList:[],
refreshing:false,
};
}
componentWillReceiveProps(nextProps){
this.setState({
suggestionList: nextProps.result.suggestionsArray ,
lastSuggestionKey : nextProps.result.lastSuggestionKey,
refreshing : false
});
}
handleRowPress = (item) => {
this.props.navigation.navigate('UserDetails', item);
};
handleMoreRequest = () => {
this.props.getOld(this.state.lastSuggestionKey);
};
handleRefresh = () => {
this.setState({
lastSuggestionKey: '',
refreshing: true
});
this.props.getAll();
};
componentWillMount() {
this.props.getAll();
}
render() {
return (
<View style={styles.containerStyle}>
<FlatList
style={{backgroundColor: colors.background}}
data={this.state.suggestionList}
renderItem={(item) =>
<CardItem contact={item.item}
onPress={() => this.handleRowPress(item)}
onCommentPress={() => this.props.navigation.navigate('SuggestionList')}/>
}
keyExtractor={item => item.suggestionid}
refeshing={this.state.refreshing}
onRefresh={() => this.handleRefresh()}
onEndReached={this.handleMoreRequest}
onEndReachedThreshold={0.7}
/>
</View>
);
}
}
const styles = StyleSheet.create({
containerStyle:{
flex:1,
backgroundColor: colors.background
},
});
function mapStateToProps({ suggestion }) {
return {
result: suggestion.result,
};
}
export default connect(mapStateToProps, actions)(Home);
You have a typo on your FlatList props, it should be refreshing instead of refeshing.

React Native - Conditional Styles on Parent Based on Child State

I was following the React Native tutorial and have tried to adapt it to show a list of songs rather than movies and add in a toggling ability using the Switch component.
I managed to get this to work but now I am trying to send the value of the switch back to the parent so that a conditional style can be applied.
When I attempted to do this, I get an error saying
undefined is not an object (evaluating 'this.state.played')
which seems sensible since the console statement in the togglePlayed never seems to be called.
import React, {
AppRegistry,
Component,
Image,
ListView,
StyleSheet,
Text,
View,
Switch
} from 'react-native';
var SONGS_DATA = {
"songs" : [
{
"title" : "I Heard React Was Good",
"artist" : "Martin",
"played" : false
},
{
"title" : "Stack Overflow",
"artist" : "Martin",
"played" : false
}
]
}
var BasicSwitchExample = React.createClass({
getInitialState() {
return {
played: false
};
},
handlePlayed(value) {
console.log('Switch has been toggled, new value is : ' + value)
this.setState({played: value})
this.props.callbackParent(value);
},
render() {
return (
<View>
<Switch
onValueChange={this.handlePlayed}
style={{marginBottom: 10}}
value={this.state.played} />
</View>
);
}
});
class AwesomeProject extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
loaded: false,
};
}
componentDidMount() {
this.fetchData();
}
getInitialState() {
return {
played: false
};
}
togglePlayed(value) {
// this is never reached
this.setState({played: value});
console.log('Song has been played? ' + this.state.played);
}
fetchData() {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(SONGS_DATA.songs),
loaded: true,
});
}
render() {
if (!this.state.loaded) {
return this.renderLoadingView();
}
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderSong}
style={styles.listView}
/>
);
}
renderLoadingView() {
return (
<View style={styles.container}>
<Text>
Loading songs...
</Text>
</View>
);
}
renderSong(song) {
return (
// not sure if this syntax is correct
<View style={this.state.played ? 'styles.container' : 'styles.played'}>
<View style={styles.half}>
<Text style={styles.title}>{song.title}</Text>
<Text style={styles.artist}>{song.artist}</Text>
</View>
<View style={styles.half}>
<BasicSwitchExample callbackParent={() => this.togglePlayed} />
</View>
</View>
);
}
}
var styles = StyleSheet.create({
/* styles here */
});
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
React Native Playground
Any pointers would be great as I am new to React and especially React Native.
You forgot to bind your function to your component, it should look like this
class BasicSwitchExample extends Component{
constructor(props){
super(props);
this.state = {
played: false
};
this.handlePlayed = this.handlePlayed.bind(this);
}
handlePlayed(value){
this.setState({played: value});
this.props.callbackParent(value);
}
render() {
return <View>
<Switch
onValueChange={this.handlePlayed}
style={{marginBottom: 10}}
value={this.state.played} />
</View>
}
}
class AwesomeProject extends Component {
constructor(props) {
super(props);
this.renderSong = this.renderSong.bind(this);
this.togglePlayed = this.togglePlayed.bind(this);
this.fetchData = this.fetchData.bind(this);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
loaded: false,
};
}
componentDidMount() {
this.fetchData();
}
togglePlayed(value) {
// this is never reached
this.setState({played: value});
console.log('Song has been played? ' + this.state.played);
}
fetchData() {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(SONGS_DATA.songs),
loaded: true,
});
}
render() {
if (!this.state.loaded) {
return this.renderLoadingView();
}
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderSong}
style={styles.listView}
/>
);
}
renderLoadingView() {
return (
<View style={styles.container}>
<Text>
Loading songs...
</Text>
</View>
);
}
renderSong(song) {
return (
// not sure if this syntax is correct
<View style={this.state.played ? 'styles.container' : 'styles.played'}>
<View style={styles.half}>
<Text style={styles.title}>{song.title}</Text>
<Text style={styles.artist}>{song.artist}</Text>
</View>
<View style={styles.half}>
<BasicSwitchExample callbackParent={this.togglePlayed} />
</View>
</View>
);
}
}

passing extraData to FlatList isn't working

I followed https://facebook.github.io/react-native/releases/next/docs/flatlist.html to make a FlatList and also passed this.state to extraData but still, once I delete an item, the item is still shown. I have also logged this.state to make sure the item is deleted and it indeed did. My code is below:
class DescriptionItem extends React.PureComponent {
render() {
return (
<TouchableOpacity
style={this.props.containerStyle}
onPress={(event) => {this.props.onPress(this.props.value)}}>
<Text style={this.props.style}>{this.props.value}</Text>
</TouchableOpacity>
)
}
}
export default class CardWorkDescriptionsList extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
error: null,
refreshing: false,
};
}
_notifyItemSelected(text) {
if(this.props.onItemSelected) {
this.props.onItemSelected(text)
}
}
_onItemSelected = (selectedItem) => {
var array = this.state.data;
var index = array.indexOf(selectedItem)
array.splice(index, 1);
console.log(array)
this.setState({data: array });
console.log("yeah",this.state.data)
this._notifyItemSelected(selectedItem);
}
makeRemoteRequest = () => {
//TODO: fetch data
this.setState({data: descriptionsFake})
}
componentDidMount() {
this.makeRemoteRequest();
}
render() {
return (
<View style={styles.cardLight}>
<FlatList
data={this.state.data}
extraData={this.state}
renderItem={(item) => (
<DescriptionItem
containerStyle={styles.itemContainer}
style={styles.content}
value={item.item}
onPress={(selectedItem)=>this._onItemSelected(selectedItem)}/>
)}
keyExtractor={item => item.substring(0,20)}
/>
</View>
);
}
}
Try extending React.Component instead of PureComponent

Populate view with data from web-service/API

I am trying to use data for an API in React Native to create multiple views.
I have used the code below but the page renders before the web service response so i keep this error:
Unhandled JS Exception: null is not an object (evaluating 'this.state.user.map')
export default class Component6 extends Component {
constructor(props) {
super(props);
this.state = {
user: null
}
}
componentDidMount() {
this.fetchUsers();
}
fetchUsers() {
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((response) => {
this.setState({
});
});
}
render() {
contents = this.state.user.map(function (item) {
return (
<View key={item.id} style={styles.content}>
<Text>{item.email}</Text>
</View>
);
});
return (
{contents}
);
}
}
AppRegistry.registerComponent('Component6', () => Component6);
You can provide an 'if' statement, and also its better to move your contents outside of render so it's not redefining it on every render:
export default class Component6 extends Component {
constructor(props) {
super(props);
this.state = {
user: null
}
}
componentDidMount() {
this.fetchUsers();
}
fetchUsers() {
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((response) => {
item = this.viewconstur(response),
this.setState({
user: item
});
});
}
renderContents = () => {
if (this.state.user) {
this.state.user.map((item) => (
<View key={item.id} style={styles.content}>
<Text>{item.email}</Text>
</View>
));
}
}
render() {
return (
<View>
{this.renderContents()}
</View>
);
}
}

Resources