I'm new to React, what I'm trying to do is call my API with a GET request to change the status of an elevator to "Operational" and it's color status from red to green. The problem is that it doesnt seem to call the API and brings me back to my previous screen when I click CONFIRM.
the function for my call to the API looks like this
function ElevatorStatusScreen({navigation, route}) {
const { Elevator } = route.params;
const [elevatorStatus, setEleStatus] = React.useState(Elevator.status);
const [statusColor, setColorStatus] = React.useState('red');
// Call to the api to update the status of an elevator
const endtask = () => {
axios.get(`https://apilink/api/Elevators/update/${Elevator.id}/Operational`)
.then(response => {
if(response.status == 200){
Alert.alert('Status has been changed to Operational!')
setColorStatus('green')
setEleStatus('Operational');
}
})
}
return (
<ImageBackground
style={styles.background}
source={require('../assets/white.jpg')}
>
<Text style={styles.title}>Elevator: {Elevator.id}</Text>
<Text style={{ color: statusColor }}>{elevatorStatus}</Text>
{elevatorStatus === 'Stopped' ? (
<TouchableOpacity style={styles.endTask} onPress={() => endtask()}>
<Text style={styles.endText}>END TASK</Text>
</TouchableOpacity>
)
:
<TouchableOpacity style={styles.confirm} onPress={() => {
navigation.goBack()
}}>
<Text style={styles.endText}>CONFIRM</Text>
</TouchableOpacity>
}
</ImageBackground>
);
}
Not sure what I'm doing wrong. This is my endpoint in a C# project coming from my elevators controller. (I tested it and it works)
[HttpGet("update/{id}/{status}")]
public async Task<dynamic> test(string status, long id)
{
var elevator = await _context.elevators.FindAsync(id);
elevator.Status = status;
await _context.SaveChangesAsync();
return elevator;
}
the endpoint: //apilink/api/Elevators/update/1/Operational returns a JSON like this in my browser
{ "id":1, "status":"Operational", "columnId":1, "serialNumber":"666999990867" }
let me know if you need more code and thanks for your help.
The problem was that my elevatorStatus was 'offline' and NOT 'Stopped' in my database...sorry about that
Related
well first i need to display the existing image that comes from API in react native.
then i need to update the existing image and replace with new picture.
Code:
<FlatList
data={filePath}
keyExtractor={(item, index) => index}
renderItem={({item}) => {
setImageName(item.fileName);
setImageType(item.type);
setImageUri(item.uri);
return (
<View>
<Image source={{uri: item.uri}} style={styles.imageStyle} />
</View>
);
}}
/>
button where i set my new picture
<GlobalButton
onPress={() => {
chooseFile('photo');
}}
text={'Add Image'}
/>
const chooseFile = type => {
let options = {
mediaType: type,
maxWidth: 300,
maxHeight: 550,
quality: 1,
};
launchImageLibrary(options, response => {
if (response.didCancel) {
showError('User cancelled camera picker');
return;
} else if (response.errorCode == 'camera_unavailable') {
showError('Camera not available on device');
return;
} else if (response.errorCode == 'permission') {
showError('Permission not satisfied');
return;
} else if (response.errorCode == 'others') {
showError(response.errorMessage);
return;
}
setFilePath(response.assets);
});
};
i get the image uri from API . i have showed it in return but it shows me two picture the existing one and new one
well first you need to make a state and set it to true like this one
const [newImageSelected, setNewImageSelected] = useState(false)
when you pick a new image from image picker then set this state to
true
const chooseFile = type => {
let options = {
mediaType: type,
maxWidth: 500,
maxHeight: 500,
quality: 1,
};
launchImageLibrary(options, response => {
if (response.didCancel) {
showError('User cancelled camera picker');
return;
} else if (response.errorCode == 'camera_unavailable') {
showError('Camera not available on device');
return;
} else if (response.errorCode == 'permission') {
showError('Permission not satisfied');
return;
} else if (response.errorCode == 'others') {
showError(response.errorMessage);
return;
}
setFilePath(response.assets);
setNewImageSelected(true);
});
};
then in return write set the condition if image is already existed
then it only shows the one picture which you are getting from the. and
when you select the new image the existing image replaced with the new
one check the below code maybe it helps you:
{newImageSelected ? (
<FlatList
data={filePath}
keyExtractor={(item, index) => index}
renderItem={({item}) => {
setImage(item.fileName);
setImageUri(item.uri);
setImageType(item.type);
return (
<View>
<Image
source={{uri: item.uri}}
style={styles.imageStyle}
/>
</View>
);
}}
/>
) : (
<Image
source={{uri: `existing image URL`}}
style={styles.imageStyle}
/>
)}
To update your screen with your data , you need to use state
To understand how it works first refer this link so you can understand how it works and how you can use it
https://reactnative.dev/docs/state.html
After that you can check how flatlist work because as per your code , you are not much aware with react native ..
FlatList accept array as data not object
here you can refer documentation
https://reactnative.dev/docs/flatlist
I'm working on a tours app which has a ratings component in the details screen, whenever an user votes it gets saved using a device token as ID, i need to make it work in a way that when i go back to the tours list and then click the on tour i already voted (or another one i haven't) it needs to show me the previous rating i gave, say if i gave it 3 stars i want to have those 3 stars painted the next time i click on said tour, or show 0 if i haven't rated yet. This is what im currently doing:
const [defaultRating, setdefaultRating] = useState(0);
const starImageFilled = 'https://raw.githubusercontent.com/AboutReact/sampleresource/master/star_filled.png';
const starImageCorner = 'https://raw.githubusercontent.com/AboutReact/sampleresource/master/star_corner.png';
const CustomRatingBar = () => {
return (
<View style={styles2.customRatingBarStyle}>
{maxRating.map((item, key) => {
return (
<TouchableOpacity
activeOpacity={0.7}
key={item}
onPress={() => {
setdefaultRating(item);
attempVotation(detail, item)
previousRate.current = item;
console.log(previousRate.current)
}}>
<Image
style={styles2.starImageStyle}
source={
item <= defaultRating
? { uri: starImageFilled }
: { uri: starImageCorner }
}
/>
</TouchableOpacity>
);
})}
</View>
);
}
const attempVotation = (tour, votacion) => {
setIsLoadingVote(true);
wretch(`${Config.API_URL}${Endpoints.tourVotacion}`)
.post({
"TourId" : tour.Id,
"DeviceId" : deviceToken,
"Clasificacion" : votacion
})
.json((json) => {
setIsLoadingVote(false);
Alert.alert('Informacion', json, [
{text: 'OK'},
]);
})
.catch((error) => {
Alert.alert('Error', 'There was an error saving your rating, try again.', [
{text: 'OK'},
]);
setIsLoadingVote(false);
});
};
Right now everything works fine, i just need to do what i previously mentioned.
I am getting TypeError: undefined is not an object (evaluating 'n._viewer.saveDocument') when I click on save button. I think the filepath to save document is not passing inside the overlay. I could be wrong. Can anyone tell me what am I doing wrong here?
render() {
var filepath;
if (this.props.dsType == "fileDocument") {
if (path == fileContent.value) {
filepath = path.uri;
} else {
<h1>Unable to render document.</h1>;
}
}
//value in filepath
console.info("filepath =", filepath);
return (
<View style={{ flex: 1 }}>
<DocumentView
//ref={(c) => this._viewer = c}
document={filepath}
onDocumentLoaded={path => {
console.info("The document has finished loading:", path);
}}
/>
<View style={styles.button}>
<Button
onPress={() => {
// Manual Save
this._viewer.saveDocument().then((filePath) => {
console.log('saveDocument:', filePath);
});
}}
title="Save"
/>
</View>
</View>
);
}
return null;
}
It seems you have commented out the line that should assign the viewer instance. As mentioned, that line should be uncommented so that this._viewer can be assigned a reference. If you are unsure, you can refer to the example code that is available on GitHub: https://github.com/PDFTron/pdftron-react-native/blob/e19b4970357f9ed2443696eb989f1c91c1905911/example/App.js#L82.
So I'm building a DnD app for character sheet management, where it displays the skills and whatnot.
In it I have a class(AbiltityClass) that stores a map of other classes(SkillClass) inside of a variable(_aSkills).
export default class AbilityClass {
constructor(name, aVal, aMod) {
this._abilityName = name; // string
this._abilityVal = aVal; // int
this._abilityMod = aMod; // int
this._aSkills = new Map(); // map of SkillClass objects
}
}
export default class SkillClass {
constructor(name, prof, mod, bonus){
this._nameSkill = name; // string
this._profSkill = prof; // bool
this._modBonus = bonus; // int
this._modSkill = this.evalMod(mod); // int
}
evalMod(mod) {
return mod + this._modBonus;
}
}
The _aSkills variable was originally an Array of SkillClasses, but due to ease-of-accessing, I decided that a Map would be better.
I have a process that will basically iterate through each element in _aSkills and create components out of them through the skillFactory and buildSkill functions which should be placed in the brackets where the skillFactory function is called.
const AbilityContainer = (props) => {
const buildSkill = (value, key) => {
return(
<SkillSet
key={Math.random()}
skillName={key}
prof={value._profSkill}
skillVal={value._modSkill}
setProf={()=>{}}
/>
);
}
const skillFactory = () => {
return(props.ability._aSkills.forEach(buildSkill));
}
return(
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.header_text}>
{props.ability._abilityName}
</Text>
</View>
<View style={styles.statBox}>
<View style={styles.ability}>
<StackedHex isAbility={true} lowerVal={props.ability._abilityVal}/>
</View>
<View style={styles.skills}>
{skillFactory()} // =================> The function call in question
</View>
</View>
</View>
);
};
My issue is that either skillFactory or buildSkill is not returning the SkillSet component.
I've used some print logs and I've verified that buildSkill is receiving the correct data, but something isn't working. I don't get any errors or warnings, and the place where the SkillSet components should be is just empty.
As I said, I changed the _aSkills variable from an Array to a Map recently, and it was working as an Array. This is the format of my previous code:
const AbilityContainer = (props) => {
const buildSkill = (skill) => {
return(
<SkillSet
key = {Math.random()}
prof={skill._profSkill}
setProf={skill._profFunc}
skillName={skill._nameSkill}
skillVal={skill._modSkill}
/>
);
}
const skillFactory = () => {
return (props.ability._aSkills.map(x => buildSkill(x)));
}
return(
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.header_text}>
{props.ability._abilityName}
</Text>
</View>
<View style={styles.statBox}>
<View style={styles.ability}>
<StackedHex isAbility={true} lowerVal={props.ability._abilityVal}/>
</View>
<View style={styles.skills}>
<SkillSet
prof={props.ability._saveProf}
setProf={props.ability._saveProfFunc}
skillName={'Save'}
skillVal={props.ability._saveMod}
/>
{skillFactory()}
</View>
</View>
</View>
);
};
I'm using Android Studio for this build and I'm still relatively new to react-native. I triple-checked all my other components and their stylesheets to make sure they weren't interfering, so I know it has something to do with the AbilityContainer.
I've read up on the forEach function for Maps and as far as I can tell, I'm doing it right, but I feel like there is something that forEach is doing that I don't understand in terms of how it returns things.
Does anyone have any idea what the issue could be?
Thanks in advance.
forEach does something for each element, but doesn't return anything (even if you return in the callback, that's just returning from the cb, not the equivalent of returning from a .map) which is why that version isn't working. If you convert it back to an array ([...props.ability._aSkills].map...) this will give you an array of arrays ([key, value]) from your Map. You could also use a for..of loop over _aSkills.entries().
So now knowing that forEach doesn't return anything, I just added a variable and gave my buildSkill function something to return to.
Here's what I did:
const AbilityContainer = (props) => {
let skills = new Array();
const buildSkill = (value, key) => {
skills.push(<SkillSet
key={Math.random()}
skillName={key}
prof={value._profSkill}
skillVal={value._modSkill}
setProf={()=>{}}
/>);
}
const skillFactory = () => {
props.ability._aSkills.forEach(buildSkill);
return(skills);
}
...
};
I got this simplified code
class Request extends Component {
constructor(props){
super(props);
this.Remove = this.Remove.bind(this)
}
componentWillMount(){
firebase.database().ref('/Users/' + AuthID).orderByChild('UserRequests').on("value", function(snapshot) {
snapshot.forEach((child) => {
Name = child.val().Name;
UserID = child.val().UserID;
obj = {key: keyIndex++, Name: Name, ID: UserID};
Requests.push(obj)
});
self.setState({Array: Requests});
});
}
//Need to call map func again as soon as user use Remove func and remove data
RenderUsers = () => {
return this.state.Array.map((Data) => (
<View key={Data.key}>
<TouchableHighlight onPress={() => {
this.Remove(Data.ID, Data.Name, Data.key);
}}>
<Text> Remove </Text>
</TouchableHighlight>
</View>
))
};
Remove = (ID, Name, KeyIndex) => {
this.state.Array.splice(KeyIndex, 1);
firebase.database().ref('Users/' + AuthID + '/UserRequests/').child(ID).remove();
//this.RenderUsers();
};
render(){
<View>
{this.RenderUsers()}
</View>
}
}
Let's say map function rendered 10 views. As soon as user clicked on a TouchableHighlight it removes from Firebase right View (request) and it doesn't exist anymore. Unfortunately I can't re-map array after data are deleted. I tried many ways but nothing worked. I thought problem is that I get data in componentWillMount. So it can't get data from Firebase after first mount anymore but if I add Request to database when app is running on that screen it appears immediately. Problem shouldn't be in componentWillMount function.