How can I update a variable after render? - react-native

Hi this is my code in App.js
var music = {
name: "Starboy",
artist: "The Weeknd",
albumArt: "",
length: "4:20",
audioURL:"",
};
export default class App extends Component
{
render() {
return (
<Image style={styles.albumArt} source={{ uri:music.albumArt }} />
);
}
};
I have another function in lastFM.js
export function getAlbumArt(albumName)
{
fetch('http://ws.audioscrobbler.com/2.0/?method=album.search&album='+albumName+'&api_key=MY_API_KEY&format=json&limit=1')
.then((response) => response.json())
.then((result) => {
const image = result.results.albummatches.album[0].image[2]['#text'];
console.log(image);
return image;
})
.catch((error) => {
console.log("ERROR: "+error);
});
}
How can I update music.albumArt in App.js and re-render Image inside App.js Render?

This might help. Re-render happens when you change the state of the component. So, here we are updating the state once we get data from the API.
export default class App extends React.Component {
constructor() {
super();
this.state = {
name: "Starboy",
artist: "The Weeknd",
albumArt: "",
length: "4:20",
audioURL: ""
};
}
componentDidMount(){
fetch('http://ws.audioscrobbler.com/2.0/?method=album.search&album='+albumName+'&api_key=MY_API_KEY&format=json&limit=1')
.then((response) => response.json())
.then((result) => {
const image = result.results.albummatches.album[0].image[2]['#text'];
console.log(image);
this.setState({...this.state, albumArt: image });
})
.catch((error) => {
console.log("ERROR: "+error);
});
}
render() {
return <Image style={styles.albumArt} source={{ uri: this.state.albumArt }} />;
}
}

Related

Can't get the userID(PlayerID). It's undefinded (ReactNative, OneSignal)

Via my application I will send notification throught OneSignal. But I can't get userID from OneSignal. I read this userID from GET request and save it in DB. After I send notification via PHP.
How I can get this userID If I always get undefined?
export default class App extends Component {
constructor(props) {
super(props);
this.WEBVIEW_REF = React.createRef();
}
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
OneSignal.setLogLevel(6, 0);
OneSignal.setAppId("fdb89158-4072-4964-b490-6ba70fb6b5fd");
OneSignal.promptForPushNotificationsWithUserResponse(response => {
});
OneSignal.setNotificationWillShowInForegroundHandler(notificationReceivedEvent => {
let notification = notificationReceivedEvent.getNotification();
console.log("notification: ", notification);
const data = notification.additionalData
console.log("additionalData: ", notification.additionalData);
notificationReceivedEvent.complete(notification);
});
OneSignal.setNotificationOpenedHandler(notification => {
});
OneSignal.addPermissionObserver(event => {
console.log("OneSignal: permission changed:", event);
});
OneSignal.addSubscriptionObserver(event => {
console.log("OneSignal: subscription changed to userId:", event.to.userId);
});
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
handleBackButton = ()=>{
this.WEBVIEW_REF.current.goBack();
return true;
}
onNavigationStateChange(navState) {
this.setState({
canGoBack: navState.canGoBack
});
}
render() {
const deviceState = OneSignal.getDeviceState();
return (
<WebView
source={{ uri: 'https://www.google.com/search?q='+ deviceState.userId}}
style={{ marginTop: 35 }}
ref={this.WEBVIEW_REF}
onNavigationStateChange={this.onNavigationStateChange.bind(this)}
/>
);
}
}
getDeviceState returns a asynchronous so make sure you're awaiting on it.

Display datas with Axios (React Native)

I am trying to display data that I fetched with Axios. They came as an array. Because of this I cant show them. What should I do?
Here is my fetch code
componentDidMount() {
axios.post('http://192.168.1.106:80/partner_project_backend/project_list.php')
.then((response) => {
console.log(response.data)
})
.catch((error) => {
console.error(error);
});
}
Here is my console.log
I'm guessing you are getting the API response correctly and your only intention is to display the data in your application. If so, you could use the FlatList component from React Native
import React from 'react';
import { FlatList, Text } from 'react-native';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
};
}
componentDidMount() {
axios.get('http://192.168.1.106:80/partner_project_backend/project_list.php')
.then((response) => {
this.setState({ data: response.data });
})
.catch((error) => {
console.error(error);
});
}
render() {
return (
<FlatList
data={data}
renderItem={({ item }) => (
<Text>{item.name}</Text> // render your view here
)}
keyExtractor={item => item.id}
/>
);
}
}
React more about FlatList at https://reactnative.dev/docs/flatlist
To fetch data you have to use get method NOT post
this.state ={ data : null }
componentDidMount(){
axios.get('http://192.168.1.106:80/partner_project_backend/project_list.php')
.then((response) => {
this.setState({ data : response.data })
})
.catch((error) => {
console.error(error);
});
}

Invalid hook call. Hooks can only be called inside of the body of a function component. in react native signature canvas

I am new to react native. I have react native signature canvas code which is in functional component but now I write that code in my class component code. then I am getting error like this = Invalid hook call. Hooks can only be called inside of the body of a function component. so whats the issue please help.
here is code
export default class Kyc extends Component {
constructor(props) {
super(props);
this.state = {
singleFileSIGN:''
};
}
ref = useRef();
handleSignature = (signature) => {
const path = FileSystem.cacheDirectory + 'sign.png';
FileSystem.writeAsStringAsync(path, signature.replace('data:image/png;base64,', ''), {encoding: FileSystem.EncodingType.Base64}).then(res => {
// console.log(res);
// FileSystem.getInfoAsync(path, {size: true, md5: true}).then(file => {
FileSystem.getInfoAsync(path).then(file => {
console.log(file);
this.setState({ singleFileSIGN: file.uri});
console.log(singleFileSIGN)
})
}).catch(err => {
console.log("err", err);
})
};
handleEmpty () {
console.log('Empty');
};
handleClear () {
console.log('clear success!');
};
handleEnd () {
ref.current.readSignature();
};
render () {
return (
<View style={styles.container}>
<View style={{flex: 1, width:355,
...Platform.select({
android: {
marginBottom:-80,
borderColor: '#FF8C00',
borderWidth:1
// marginBottom:-150
},
}),
}}>
<SignatureScreen style={{height: '400%'}}
ref={this.ref}
onEnd={this.handleEnd}
onOK={this.handleSignature}
onEmpty={this.handleEmpty}
onClear={this.handleClear}
descriptionText={'Sign here!'}
/>
</View>
</View>
);
}
}
Hooks only used in function components. In class use like this:
constructor(props) {
super(props);
this.ref = React.createRef();
}

React Native: Getting data from Firebase

I'm simply trying to retrieve data from the database in Firebase, and here's what I've got
var userList = [];
firebase.database()
.ref('/users/')
.once('value')
.then(snapshot => {
snapshot.forEach((doc) => {
userList.push(doc.val());
});
});
console.log(userList);
Even though I copy and pasted this code from a tutorial, the userList is empty outside of the snapshot. Can you tell me why that is?
The request to firebase is asynchronous so console.log(userList); is called before userList.push(doc.val()); gets called.
You should make userList a component state variable so that when you update it your component will re render.
Something like the following should work:
class UserListComponent extends Component {
constructor(props) {
super(props);
this.state = {
userList: [],
};
}
componentDidMount() {
this.getUsers();
}
getUsers() {
firebase
.database()
.ref('/users/')
.once('value')
.then((snapshot) => {
snapshot.forEach((doc) => {
this.setState({
userList: [...this.state.userList, doc.val()],
});
});
});
}
render() {
return (
<View>
{this.state.userList.map((item) => {
return (
<View>
<Text>{item.name}</Text>
</View>
);
})}
</View>
);
}
}

Invariant Violation in React Native: Text strings must be rendered within a <Text> component

I'm working on a React-Native project with REST APis, and I've currently got an invariant violation error. I've experienced this before, but I can't quite figure out what is causing it and how to fix it. If someone could point me in the right direction, I would really appreciate it! The full error is pictured below, and appears to be referencing a number of tags in the code, so I'm unsure exactly where it is originating. Thank you for reading, and thanks in advance!
The code is here:
import React, { Component } from 'react'
import { View, Text, Image, StyleSheet, FlatList} from 'react-native';
import * as Font from 'expo-font';
import styled from 'styled-components';
import dimensions from '../components/ScreenSize';
import colours from '../components/Colours';
import { Audio } from 'expo-av';
import { TouchableHighlight } from 'react-native-gesture-handler';
const client_id = {Client_ID}
const client_secret = {Client_Secret}
const item = ({item}) => (
<View style={{ flex:1, flexDirection: 'column', margin:1}}>
<TouchableHighlight onPress={() => this.fetchTracks(item.id)}>
<View>
<Text>{item.name}</Text>/>
</View>
</TouchableHighlight>
</View>
)
export default class HomeScreen extends React.Component {
state={
fontsLoaded:false,
}
async componentDidMount() {
await Font.loadAsync({
'montserrat-regular': require('../assets/fonts/Montserrat/Montserrat-Regular.ttf'),
'montserrat-light': require('../assets/fonts/Montserrat/Montserrat-Light.ttf'),
'montserrat-semibold': require('../assets/fonts/Montserrat/Montserrat-SemiBold.ttf'),
'montserrat-bold': require('../assets/fonts/Montserrat/Montserrat-Bold.ttf'),
}
).then(() => this.setState({ fontsLoaded:true }))
this.getToken();
this.setAudio();
}
constructor (props) {
super(props)
this.playbackInstance=null;
this.state = {
playing:false,
token: '',
DATA:[],
};
}
setAudio=() => {
Audio.setAudioModeAsync({
allowsRecordingIOS:false,
interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_DO_NOT_MIX,
playsInSilentModeIOS: true,
shouldDuckAndroid: true,
interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DO_NOT_MIX,
playThroughEarpieceAndroid: false,
});
}
componentDidCatch(error, info)
{
console.log(error, info.componentStack);
}
getToken = async() =>
{
try
{
const getspotifytoken = await fetch("https://accounts.spotify.com/api/token",
{
method:'POST',
body: `grant_type=client_credentials&client_id=${client_id}&client_secret=${client_secret}`,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const spotifytoken = await getspotifytoken.json();
this.setState({
token: spotifytoken.access_token
});
console.log(this.state.token);
}
catch(err)
{
console.log("Error fetching data", err);
}
}
search = async () => {
try
{
console.log("Searching: mood")
const spotifyApiCall = await fetch(`https://api.spotify.com/v1/browse/categories/mood/playlists?`, {
headers: {
Accept: 'application/json',
Authorization: `Bearer ${this.state.token}`,
"Content-Type":'application/json'
}
})
const spotify = await spotifyApiCall.json();
console.log("Items", spotify);
this.setState({
DATA: spotify.playlists.items,
})
}
catch (err)
{
console.log("Error fetching data", err);
}
}
fetchTracks = async (playlistId) => {
console.log('Playlist ', playlistId)
try
{
const getplaylist = await fetch(`https://api.spotify.com/v1.playlist/${playlistId}`,
{
method:'GET',
headers: {
Accept:"application/json",
Authorization:`Bearer ${this.state.token}`,
"Content-Type":"application/json"
}
});
const playlist = await getplaylist.json();
console.log('music ', playlist.tracks.items[0].preview_url);
}
catch (err)
{
console.log("Error fetching data ", err);
}
}
async _loadNewPlaybackInstance(playing, track) {
if(this.playbackInstance != null)
{
await this.playbackInstance.unloadAsync();
this.playbackInstance.setOnPlaybackStatusUpdate(null);
this.playbackInstance = null;
}
const source = {uri: track};
const initialStatus = {
shouldPlay: true,
rate: 1.0,
shouldCorrectPitch: true,
volume: 1.0,
isMuted: false
};
const {sound, status} = await Audio.Sound.createAsync(
source.initialStatus);
this.playbackInstance=sound;
this.playbackInstance.setIsLoopingAsync(false);
this.playbackInstance.playAsync();
if (this.state.selected === playlistId) {
console.log("Playing, so stop");
this.setState({selected:null});
this.playbackInstance.pauseAsync();
return;
}
this.setState({ selected:playlistId});
this._loadNewPlaybackInstance(true, playlist.tracks.items[0].preview_url);
}
render() {
if(!this.state.fontsLoaded ) {
return null
}
return (
<Container>
<Titlebar>
<Title>Music</Title>
</Titlebar>
<HeaderBar2>
<TouchableHighlight onPress={() => this.search()}>
<Header2>Playlists for your Mood</Header2>
</TouchableHighlight>
</HeaderBar2>
<View style={styles.MainContainer}>
{
this.state.DATA.length == 0 &&
<Text style={{padding:10, color:'#D3D3D3'}}/>
}
<FlatList
data = {this.state.DATA}
renderItem={item}
keyExtractor = {item.id}
numColumns={2}
extraData = {this.state}
/>
</View>
</Container>
);
}
}
I think u just have a little typo ..
check this line: <Text>{item.name}</Text>/>
change the last Text to </Text>