Working with nested array in react native - php

I am making a quiz app in react native, I have written an API in PHP which fetches the question and the options from the database, with the response from API looking something like
[{"id":2109,
"title":"\u0915\u0930\u094d\u0923\u093e\u0932\u0940 \u0928\u0926\u0940\u0915\u094b \u0938\u0939\u093e\u092f\u0915 \u0928\u0926\u0940 \u0924\u0932\u0915\u093e \u092e\u0927\u094d\u092f\u0947 \u0915\u0941\u0928 \u0939\u094b\u0907\u0928 ?",
"option":[{
"option_id":191061,
"options":"\u0939\u0941\u092e\u094d\u0932\u093e \u0915\u0930\u094d\u0923\u093e\u0932\u0940",
"correct":0
},
{
"option_id":191062,
"options":"\u0920\u0942\u0932\u094b \u092d\u0947\u0930\u0940",
"correct":0},
{
"option_id":191060,
"options":"\u092e\u0941\u0917\u0941 \u0915\u0930\u094d\u0923\u093e\u0932\u0940",
"correct":0
},{
"option_id":191059,
"options":"\u0921\u094b\u0932\u094d\u092a\u093e \u0915\u0930\u094d\u0923\u093e\u0932\u0940",
"correct":1
}
]}]
................................
and so on,
Upto now I have successfully fetched the json in my react app as the way I like. But now I want to select only one option for each question, I want the option to be highlighted as per the user selection also I have to check if the user is correct or not by verifying with the json response.
How can I achieve this?
the full code is here:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableHighlight,
Alert,
Navigator,
WebView,
ScrollView,
ListView
} from 'react-native';
export default class Api extends Component{
constructor(){
super()
this.state = {
id:'',
option_id:'',
option_option:[],
options_ans:[],
title:'',
data:[],
userSelectedIndex:-1,
}
}
componentWillMount(){
fetch('http://192.168.1.11/loksewaquiz/index.php? exam_of=kharidar', {method: 'GET'})
.then((response) => response.json())
.then((responseData) =>{
this.setState({
data:responseData,
})
})
.done();
}
onUserSelectedOption(index){
this.setState({
userSelectedIndex:index,
});
}
render(){
const result = this.state.data.map((data) =>{
const xx = data.ans_option.map((ans_option,index)=>{
return (
<TouchableHighlight onPress={()=> this.onUserSelectedOption(ans_option, index)}>
<Text key={ans_option.option_id} style={{backgroundColor: (index === this.state.userSelectedIndex) ? 'red' : 'transparent'}}> {ans_option.option_option}</Text>
</TouchableHighlight>
)
})
return(
<View>
<Text style={styles.titles}>{data.title}</Text>
{xx}
</View>
)
})
return(
<ScrollView>
{result}
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection:'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
button:{
backgroundColor:'#EEE',
padding:10,
marginRight:5,
marginLeft:5,
},
options:{
padding:10,
marginRight:5,
marginLeft:5,
backgroundColor:'#EEE',
},
titles:{
backgroundColor:'#000',
color:'#FFF',
},
selectedoptions:{
backgroundColor:'#008000',
}
});
Here is the image when I select the first option
This is when I press the third option

Something like this , updated with one of the ways highlighting can be done
onUserSelectedOption = (option, index) => {
this.setState({
userSelectedIndex: index
});
if (option.correct === 1) {
//do something
}else {
//do something
}
}
render(){
const result = this.state.data.map((data) =>{
const xx = data.option.map((option, index)=>{
return (
<TouchableHighlight onPress={() => this.onUserSelectedOption(option, index)}>
<Text key={option.option_id} style={{backgroundColor: index === this.state.userSelectedIndex ? 'red' : 'transparent' }}>{option.options}</Text>
</TouchableHighlight>
)
})
return(
<View>
<Text style={styles.titles}>{data.title}</Text>
{xx}
</View>
)
})
return(
<ScrollView>
{result}
</ScrollView>
);
}

I would actually seperate the options in a new component, and pass relevant data via props. Not an expert on js, but sounds more solid then nested map functions.

Related

How to display the users_ID on the screen with react native

I made login with PHP and React Native but now I want to display the ID of the user that's logged in. The ID should be showed on the screen that appears when the user is logged in.
I tried several things but I think the way I request the props is wrong. Because the page where I want to show never requests the data that is started in the previous page.
This is the login screen:
import React from 'react';
import { StyleSheet, Text, View, TextInput, Button } from 'react-native';
import * as Expo from 'expo';
export default class App extends React.Component {
state = {
username: '',
password: '',
response: '',
users_ID: '',
};
handleusers_usernameChange = (users_username) => {
this.setState({ users_username });
};
handleusers_passwordChange = (users_password) => {
this.setState({ users_password });
};
handleLoginPress = async () => {
const { users_username, users_password } = this.state;
try {
let response = await fetch('http://IP/CodingApp/login.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
users_username,
users_password,
}),
});
let responseJson = await response.json();
console.log(responseJson);
if (responseJson.loggedin) {
this.props.setLoggedIn(true, responseJson.users_ID);
this.setState({ users_ID: responseJson.users_ID });
} else {
this.setState({ response: 'tekst kwam niet overeen' });
}
} catch (error) {
console.error(error);
}
};
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.input}
value={this.state.users_username}
onChangeText={this.handleusers_usernameChange}
placeholder="users_username"
/>
<TextInput
style={styles.input}
value={this.state.users_password}
onChangeText={this.handleusers_passwordChange}
placeholder="users_password"
secureTextEntry
/>
<Button title="Login" onPress={this.handleLoginPress} />
<Text>{this.state.response}</Text>
</View>
);
}
}
And this is the screen that appears after the user is logged in:
import React from 'react';
import { View, Text } from 'react-native';
const EditFamily = (props) => {
return (
<View>
<Text>Your user ID is: {props.users_ID}</Text>
</View>
);
};
export default EditFamily;
Read about redux, which is a state management tool, you can save id whenever or wherever you go and use it everywhere.
https://redux.js.org/introduction/getting-started

react native 403 permission error from php api on wamp server

react native error
import React, { Component } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true
};
}
async getMovies() {
try {
const response = await fetch('http://192.168.1.6:80/p4Lite/Sept2021/react_backend/index.php');
const json = await response.json();
this.setState({ data: json });
} catch (error) {
console.log(error);
} finally {
this.setState({ isLoading: false });
}
}
componentDidMount() {
this.getMovies();
}
render() {
const { data, isLoading } = this.state;
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<Text>{item.name}, {item.email}</Text>
)}
/>
)}
</View>
);
}
};
Above is my app.js file code. It works fine on web but shows error on my android phone using expo go. I have tried various methods but till now is solution fond. I am working on localhost.
Try this on your API related folder
sudo chmod -R -f 777 /path/to/your/file/or/directory
the 403 error means that the request you made was forbidden. it is generally received when a required password is not entered.
Most likely, your API requires a password, and this was not provided by the code, the server code is miss-configured, or the server does not have the right permissions to display the result.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403
Some how it's working by changing:
Require local to Require all granted in httpd-vhosts.conf

post/passing data array in react native using axios not caught by ENDPOINT

i'm trying to make simple CRUD using axios in react-native, when i'm trying to create an add data function i'm having problems passing array data to endpoint,
note: the endpoint I created using php native,
I've tried my endpoint using POSTMAN 3 times, and it worked.
enter image description here
however, when I try to POST using axios in react native, the data in the array is not caught by the endpoint.
import React, { Component } from 'react'
import { Text, View, StyleSheet, TextInput, TouchableOpacity, Alert } from 'react-native'
import axios from 'axios'
export class CreatelData extends Component {
constructor(props) {
super(props)
this.state = {
title:'',
description: '',
}
}
onSubmit = () => {
const dataInput = {
title: this.state.title,
description: this.state.description,
}
console.warn(dataInput)
axios.post('http://my_local_ip/fullstack/smooth_test/backend/api.php?on=create', dataInput)
.then( response => {
// resultSend(response.data)
console.log('res: ', response.data)
})
.catch(err => console.log('err: ', err) )
}
render() {
return (
<View style={tampilan.container}>
<Text style={tampilan.header}>POST</Text>
<View>
<View style={tampilan.row}>
<Text>Title :</Text>
<TextInput
style={tampilan.textInput}
placeholder="Enter Title..."
onChangeText= { (value) => {this.setState( {title: value} )} }
></TextInput>
</View>
<View style={tampilan.row}>
<Text>Description :</Text>
<TextInput
style={tampilan.textInputArea}
placeholder="Enter Description..."
onChangeText= { (value) => {this.setState( {description: value} )} }
></TextInput>
</View>
<View style={tampilan.row}>
<TouchableOpacity
style={tampilan.btnSubmit}
onPress={ () => this.onSubmit() }
>
<Text style={tampilan.textbtn}>Submit</Text>
</TouchableOpacity>
</View>
</View>
</View>
)
}
}
however, when I try to view the array using console.warm(data), the data has contents, and is not empty.
enter image description here
anyone please advice and solutions..
I found some help here react native axios
axios post look like this :
const user = {
name: this.state.name
};
axios.post(`https://jsonplaceholder.typicode.com/users`, { user })
.then(res => {
console.log(res);
console.log(res.data);
})
then your code code could be look like this
const dataInput = {
title: this.state.title,
description: this.state.description,
}
console.warn(dataInput)
axios.post('http://my_local_ip/fullstack/smooth_test/backend/api.php?on=create', {dataInput})
.then( response => {
// resultSend(response.data)
console.log('res: ', response.data)
})

How to fetch php created json to react native

I've created a table in mysql, for some news data. it comprises of title, body, and link to the image. The file, is saved on example.com/api/news.php, and by following the link will result in an array, something like this:
[{"id":"1","title":"News Title 1","body":"Body 1","date":"2020-12-01","image":"Image 1","link":"Link 1"},{"id":"2","title":"Title 2","body":"Body 2","date":"2020-12-17","image":"Image 2","link":"https:\/\/google.com"},{"id":"3","title":"Title 3","body":"Body 3","date":"2020-12-24","image":"Image 3","link":""}]
In react native, I tried to fetch by following examples:
constructor(props){
super(props);
this.state = {
isLoading: true,
data: null
}
}
componentDidMount(){
return fetch('https://example.com/api/news.php')
.then((response) => response.json())
.then((json) => {
this.setState({
isLoading: false,
data: json.id,
})
})
.catch((error) => {
console.error(error);
});
}
render(){
if(this.state.isLoading){
return(
<View style={styles.container}>
<ActivityIndicator/>
</View>
)
}else{
return(
<View style={styles.container}>
<Text>Content Loaded!</Text>
</View>
)
}
}
However, the activity indicator keeps on running. While, when I tried using the original API link from the example which is https://reactnative.dev/movies.json, its working fine. May I know what is the problem that is blocking the json to be read. Thanks for your guidance.
Remove return from code and maybe you are getting an error in response, try reset isLoading state in error like
componentDidMount(){
fetch('https://example.com/api/news.php')
.then((response) => response.json())
.then((json) => {
this.setState({
isLoading: false,
data: json.id,
})
})
.catch((error) => {
console.error(error);
this.setState({ // add this code
isLoading: false
})
});
}

how to check if a new record has been added to a database in php and covert it to react native (Notification message)

I am new to react native and I am creating an app that displays a list fo podcasts which are stored in a mysql database. I then use php to get the information and convert it to json format. Once the information is covered to json I then fetch it within react native and display it within a flatlist.
I would like a notification to appear each time the podcast list has been update.
I have set up my notifications using onesignal and use node.js on my backend to create and send the notifications.
I would like to be able to listen to the database to check each time that the database has a new row and then covert this into react native so that I can send the notifications.
After doing some research I have been unable to find a solution for this.
Here is my php
<?php
include 'DBConfig.php';
$json = file_get_contents('php://input');
$obj = json_decode($json, true);
$id = $obj['id'];
$query = "SELECT * FROM SermonsTable WHERE Category ='$id'";
$result = mysqli_query($con, $query) or die("Invalid Query");
while($row = mysqli_fetch_assoc($result)){
$Item[] = $row;
$json = json_encode($Item);
}
echo $json;
?>
React Native file
export default class MainScreen extends React.Component
{
constructor(props) {
super(props);
this.state = {
isLoading: true
}
}
componentDidMount(){
const fetch = require('node-fetch');
fetch('http://03d77927eb6d.ngrok.io/AntrimElimChurch/backend/FilterCat.php', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
// Getting the id.
id: this.props.navigation.state.params.FlatListClickItemHolder
})
}).then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson
});
}).catch((error) => {
console.error(error);
});
}
FlatListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
OpenSecondActivity(id) {
this.props.navigation.navigate("Podcats", { FlatListClickItemHolder: id});
}
componentDidMount() {
this.dataSource.addEventListener('change', this.RunNotification);
}
RunNotification = () => {
fetch('http://localhost:8080/api', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}).then(res => {
console.log(res);
return res.json();
}).then(response => {
console.log(response)
this.data = response;
}).catch(error =>{
this.error = error.message || error.error;
});
};
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.MainContainer}>
<FlatList style={{paddingTop: 30}}
data={ this.state.dataSource }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={this._renderItem}
keyExtractor={(item, index) => index.toString()} />
</View>
);
}
_renderItem = ({item}) => {
return(
<View style={styles.MainView}>
<View style={{flex: 1, flexDirection: 'row'}}>
<Text style={styles.rowViewContainer} onPress={this.OpenSecondActivity.bind(this, item.id)}>{item.Name}</Text>
{/* <Text style={styles.SermonByText}>{item.SermonBy}</Text> */}
<Text style={styles.PodcastByText}> - {item.DateRecorded}</Text>
</View>
</View>
);
}
}
I am really confused as to how to do this as I am new to react native and not that confident with php.
I recommend you to use sockets.
NPM socket.io is easy to use for front End
For your backend in PHP you can use this library https://github.com/walkor/phpsocket.io
So each time a new record has been added to your database you must use an handler to send a socket request to your client

Categories