I want to understand why my Text is not rendering please and how i can get this working
import React, { Component } from 'react';
import { View,Button,Text } from 'react-native';
export default class LiveApiData extends Component {
constructor() {
super()
this.state = {data:[]}
}
componentDidMount() {
fetch("<<taking out the api key")
.then(response => response.json())
.then(new_data => {this.setState({data:new_data})})
}
render() {
return (
<View style={{ height: 200, flexDirection: 'row'}}>
<Text> {this.state.data[0]}</Text>
</View>
);
}
}
Much appreciated in advance
In the above code in the render() you are rendering the data which is an array so. If this array is a collection of objects you will need to specify the key name to render the text. If the array is of strings then it should get rendered.
I am pasting a working example for this question.Example Link
The solution will add a null check. Because the state will be empty when you are rendering at the first time.
<div style={{ height: 200, flexDirection: "row" }}>
<div> {this.state.data.length ? this.state.data[0].title : ""}. </div>
</div>
Related
I am starting to learn sliders and other basic components in react native. I would like to print the current value of the slider in the terminal. I tried putting console.log() in different places, but didn't know what I was doing and got errors.
import React, { Component } from 'react';
import { Slider, View, Text } from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
sliderValue: "0",
};
}
render() {
return (
<View
style={{
flex: 1,
padding: 20,
justifyContent: "center",
backgroundColor: "#ecf0f1",
}}>
<Text style = {{ color: "black" }}>
Value of this slider is : {this.state.sliderValue}
</Text>
<Slider
maximumValue = {10}
minimumValue = {0}
step = {1}
value = {this.state.sliderValue}
onValueChange = {sliderValue => this.setState({ sliderValue })}
/>
</View>
);
}
}
Well, you have many options here, I'll give you 2.
You can just console log in your render method
render() {
console.log(this.state.sliderValue);
//the reset of your code
}
Or you can do it inline with the setState call
onValueChange = {sliderValue => console.log(sliderValue) || this.setState({ sliderValue })}
I trying to build a weather app for my training and I have a issues.
I got a Type Error whatever I do. what I intended to do is get a json data from weathermap api and then
show some strings but I couldn't.
here is main content from My app
import React, { Component } from 'react';
import { View, StyleSheet, Text } from 'react-native';
class Content extends Component{
constructor(props) {
super(props);
this.state = {
data: this.props.weather.main,
};
}
render() {
return (
<View style={styles.content}>
<Text style={styles.city}>City Name</Text>
<Text style={styles.itemsize}>Weather {this.state.data}</Text>
<Text style={styles.itemsize}>Description</Text>
<Text style={styles.itemsize}>Temperature Celsius</Text>
<Text style={styles.itemsize}>Pressure</Text>
<Text style={styles.itemsize}>Humidity</Text>
</View>
);
}
}
const styles = StyleSheet.create({
content: {
flex: 1,
justifyContent: 'center',
alignItems:'center'
},
city: {
fontSize: 50,
padding: 20
},
itemsize: {
fontSize: 30,
padding: 5
}
})
export default Content;
and this is my upper component which is trying to get data and pass down.
import React, { Component } from 'react';
import Content from './Content';
import GetWeather from './GetWeather';
class Home extends Component {
constructor(props) {
super(props);
this._getData.bind(this);
this._getData();
this.state = {
data: null,
};
}
_getData = () => {
GetWeather.getWeather().then( json => {
console.log(json);
this.setState({data: json});
});
};
render() {
return (
<Content weather={this.state.data}/>
);
}
}
export default Home;
and last one is code that I wrote to get api data from openweathermap
function getLocation(lat, long) {
return `${API_STEM}lat=${lat}&lon=${long}&appid=${APP_ID}`;
}
function getWeather() {
return fetch(getLocation(LATTITUDE,LONGGITUDE))
.then(response => response.json())
.then(responseJson => {
return { main: responseJson.weather[0].main};})
.catch(err =>console.log(err));
}
export default {getWeather: getWeather};
In your parent component, state never gets data and always remains null. When we want to fetch data from an API, we should use a react lifecycle method called componentDidMount(). So in your parent component, you should either call your _getdata function in componentDidMount or fetch your data in the lifecycle method, like below code which is a better way in my opinion. Also, never initially set your state to null. set it to an empty object.
import React, { Component } from 'react';
import Content from './Content';
import GetWeather from './GetWeather';
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: {},
};
}
componentDidMount() {
GetWeather.getWeather().then( json => {
console.log(json);
this.setState({data: json});
});
}
render() {
console.log(this.state.data);
return (
<Content weather={this.state.data}/>
);
}
}
export default App
and then in your child component, you should either use one of updating lifecycle methods (that has risks) or you can change your child component to functional component, for you don't need state.
import React, { Component } from 'react';
import { View, StyleSheet, Text } from 'react-native';
function Content(props) {
return (
<View style={styles.content}>
<Text style={styles.city}>City Name</Text>
<Text style={styles.itemsize}>Weather {props.weather.main}</Text>
<Text style={styles.itemsize}>Description</Text>
<Text style={styles.itemsize}>Temperature Celsius</Text>
<Text style={styles.itemsize}>Pressure</Text>
<Text style={styles.itemsize}>Humidity</Text>
</View>
)
}
const styles = StyleSheet.create({
content: {
flex: 1,
justifyContent: 'center',
alignItems:'center'
},
city: {
fontSize: 50,
padding: 20
},
itemsize: {
fontSize: 30,
padding: 5
}
})
export default Content;
The main problem is that this.state.data in the Home component is set after the Content component is created (after its constructor function is called).
This will generate a TypeError because this.props.weather is undefined and you are trying to access a property this.props.weather.main.
The easiest way to solve this will be to use the props object directly instead of adding those props to the state, here is an example:
<Text style={styles.itemsize}>Weather {this.props.weather}</Text>
Before the request finishes you already set this.state.data inside Content to null and it will not get updated when the component re-renders because the constructor only runs once on mount.
Setting state from props is an anti pattern and should be used only in rare situations.
Instead, read the weather data from this.props which will get updated once the parent component updates his state
You would also need to check if this.props.weather is null before you access .main inside this.props.weather
class Content extends Component {
render() {
const { weather } = this.props
return (
<View style={styles.content}>
<Text style={styles.city}>City Name</Text>
<Text style={styles.itemsize}>
Weather {weather ? weather.main : null}
</Text>
<Text style={styles.itemsize}>Description</Text>
<Text style={styles.itemsize}>Temperature Celsius</Text>
<Text style={styles.itemsize}>Pressure</Text>
<Text style={styles.itemsize}>Humidity</Text>
</View>
)
}
}
I want to display the details of what's user clicks in the ResultCard.
I want to replace the divs contents (currently displayed results) with rendered html based on the result found in my elastic search cluster(res) when user click the url in the resultcard.
I tried adding onclick properties but nothing happens. Reactivesearch documentation don't list this attribute.
Of course, I could pass argument in the url properties of ResultCard and redirect user to another page but page would be reloaded completely (with the menus defined in index.js and the footer)
I think creating parent component with state mirroring the currently displayed children component in the div is the way to go.
But, how to run a javascript for setting the state when user click in the resultcard?
import React, { Component } from 'react';
import { ReactiveBase, CategorySearch, SingleRange, ResultCard } from '#appbaseio/reactivesearch';
class App extends Component {
render() {
return (
<ReactiveBase
app="artists"
url="https://admin:xxxxxxx#node1.searchevolution.com:9200"
type="_doc">
<div style={{ display: "flex", "flexDirection": "row" }}>
<div style={{ display: "flex", "flexDirection": "column", "width": "40%" }}>
<CategorySearch
componentId="searchbox"
dataField="nom"
categoryField="occupations.keyword"
type="artists"
placeholder="Search for Artists, Painter, Sculptor, Photographs"
style={{
padding: "5px",
"marginTop": "10px"
}}
/>
</div>
<ResultCard
componentId="result"
dataField="nom"
title="Results"
from={0}
size={6}
pagination={true}
onclick="alert('Message à afficher');"
react={{
and: ["searchbox"]
}}
onData={(res) => {
return {
image: "data:image/png;base64,iVBORw0KGgoA",
title: res.occupations,
description: res.nom,
url: "/details/" + res
}
}}
style={{
"width": "60%",
"textAlign": "center"
}}
/>
</div>
</ReactiveBase>
);
}
}
export default App;
Expected result is to change the div content with the rendered html from another component (not still coded).
The handler should be called onClick instead of onclick (Even though it looks like HTML, this is JSX, so handlers need to be camelCase).
Also, your code will not call alert unless you put it in curly braces (which tells JSX to execute code). One more thing: you want to wrap it in a function, otherwise the alert will be called when the component mounts, and not on a click.
onClick={() => alert('Message à afficher')}
EDIT: I think I misunderstood your question. If I'm understanding correctly, you're right and you want to handle the click in the App component. Something like this:
class App extends Component {
state = {
showResultCard = true,
}
handleClick = () => {
this.setState({ showResultCard: false });
}
render() {
<ReactiveBase>
...
{this.state.showResultCard ? (
<ResultCard onClick={this.handleClick} ... />
) : (
<OtherComponent ... />
)}
</ReactiveBase>
}
}
finally got it working by using the base component ReactiveList instead ReactiveCard.
ReactiveCard onData callback function is an object with image, title, description and url fields. No way, to return something else. No way to use onClick property.
So, better use the base component and do some html and css myself
import React, { Component } from 'react';
import { ReactiveBase, CategorySearch, SingleRange, ResultCard, ReactiveList} from '#appbaseio/reactivesearch';
class App extends Component {
constructor(props) {
super(props);
this.state = {
showResultCard : true,
};
}
handleClick = () => {
this.state.showResultCard ?
this.setState({ showResultCard: false }) : this.setState({ showResultCard: true });
}
render() {
return (
<ReactiveBase
app="artists"
url="https://admin:xxxxxxxxxx#node1.searchevolution.com:9200"
type="_doc">
{this.state.showResultCard ? (
<div style={{ display: "flex", "flexDirection": "row" }}>
<div style={{ display: "flex", "flexDirection": "column", "width": "40%" }}>
<CategorySearch
componentId="searchbox"
dataField="nom"
categoryField="occupations.keyword"
type="artists"
placeholder="Search for Artists, Painter, Sculptor, Photographs"
style={{
padding: "5px",
"marginTop": "10px"
}}
/>
</div>
<ReactiveList
componentId="result"
dataField="nom"
className="result-list-container"
size={5}
onData={(res) => <div>{res.nom}<button onClick={this.handleClick}>tttt</button></div>}
pagination
URLParams
react={{
and: ['searchbox'],
}}
/>
</div> ) : (<button onClick={this.handleClick}>back</button>)}
</ReactiveBase>
);
}
}
export default App;
I have a problem with making my ButtonGroup dynamic, I tried a lot but nothing seems to work, can someone help me, please?
import React from 'react';
import { ButtonGroup } from 'react-native-elements';
export default class WebsiteFilter extends React.Component {
constructor(props) {
super(props);
this.state = {
WebsiteFilter: 3
};
}
updateIndex = ( WebsiteFilter ) => this.setState({ WebsiteFilter })
render() {
const buttons= ['Vergelijkdirect', 'Ivanhoe', 'Bespaarcoach'];
let { WebsiteFilter } = this.state;
return (
<ButtonGroup
textStyle={{ textAlign: 'center', fontSize: 12, }}
onPress={this.updateIndex}
WebsiteFilter={WebsiteFilter}
buttons={buttons}
/>
);
}
}
Instead of:
const buttons= ['Vergelijkdirect', 'Ivanhoe', 'Bespaarcoach'];
I need to display the domain of this array:
[{"id":127,"created_at":"2015-11-02 15:35:11","updated_at":"2016-09-19 11:42:10","deleted_at":null,"customer_id":66,"domain":"http:\/\/vergelijkdirect.com","google_id":"UA-97758230-1","currency_id":1,"root":1,"screenshot":"","integration_date":"2016-09-19 11:42:10"},{"id":283,"created_at":"2017-01-13 16:54:24","updated_at":"2017-01-13 16:54:24","deleted_at":null,"customer_id":66,"domain":"https:\/\/ivanhoe.io","google_id":null,"currency_id":1,"root":0,"screenshot":"","integration_date":null},{"id":327,"created_at":"2017-06-14 19:29:42","updated_at":"2017-06-23 17:29:01","deleted_at":null,"customer_id":66,"domain":"http:\/\/bespaarcoach.vergelijkdirect.com","google_id":"UA-39848260-2","currency_id":1,"root":0,"screenshot":"","integration_date":"2017-06-23 17:29:01"}]
The property buttons expects an array of strings or components, so in your case, you need to map the array and to return the property that you want to display:
data.map(e => e.id)
Also, the ButtonGroup component does not have a property WebsiteFilter, it has to be selectedIndex.
Your component should look like this:
<ButtonGroup
textStyle={{ textAlign: 'center', fontSize: 12, }}
onPress={this.updateIndex}
selectedIndex={this.state.WebsiteFilter}
buttons={data.map(e => e.id)}
/>
Here is a working demo.
I'm trying to make a custom router component, that will pick a layout dynamically. But, when I'm trying to render layout dynamically I receive blank page.
What I'm doing wrong?
import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';
import WelcomePageLayout from '../layouts/welcome-page';
import GamePageLayout from '../layouts/game';
export default class Router extends Component {
constructor(props) {
super(props);
this.layouts = [
WelcomePageLayout,
GamePageLayout
];
this.state = {
currentLayout: 0
};
}
render() {
const layout = this.layouts[this.state.currentLayout];
return (
<View style={styles.container}>
{ layout }
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: 'column',
flex: 1,
paddingTop: 60,
alignItems: 'center',
justifyContent: 'center',
marginBottom: 100
}
});
A step ago, before adding this dynamic render everything was working as expected. So I'm pretty sure it's something about that.
Thanks in advance.
You are just passing the component as a child to View. Make sure you render it as well:
render() {
const Layout = this.layouts[this.state.currentLayout];
return (
<View style={styles.container}>
<Layout />
</View>
);
}