Hello I am in the middle fixing a bug and whould like some outside eyes for some support.im using axios to retreive a class from my springboot tomcat server.the information is fine in the controller up to the return portion once it goes to my front end though thats where the problem occurs I get an object like this upon res.data {#id:'1'}.
my class
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIdentityInfo(generator= JSOGGenerator.class)
#Getter
#Setter
#Builder
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "gender")
public class Gender implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false)
private String gender;
#OneToMany(fetch=FetchType.LAZY, mappedBy="gender")
private Set<User> users;
}
the react page.
import React, { useState,memo,useEffect }from "react";
import axios from 'axios';
import JSOG from 'jsog';
import {decrypt} from "../../Util/jsogRetreival.js";
import Autocomplete from '../../Util/autocomplete';
let Gender=(props)=>{
let[gender,setgender]=useState({});
let[list,setList]=useState([]);
let[error,setError]=useState("");
let[currentValue,setCurrentValue]=useState("");
let[fullList,setFullList]=useState([]);
useEffect(() => {
let getValue="";
const fetchData = async () => {
if(props.id!==-1){
await axios.get(
'http://localhost:8080/gender/getById/'+props.id)
.then(res => {
setgender(res.data);
}).catch(
function (error) {
console.log(error);
});}
else{
await axios.get(
'http://localhost:8080/gender/getDummy')
.then(res => {
//
//where i pause my code and get the #id in res.data
//
//
let genderOf=decrypt(res.data);
let idontknow=JSOG.decode(res.data);
let fuck= JSOG.parse(idontknow);
setgender(res.data);
}).catch(
function (error) {
console.log(error);
});
}
let fromList=[];
await axios.get(
'http://localhost:8080/gender')
.then(res => {
if(res.data.length<1){
}
else{
fromList=decrypt(res.data);
}
setFullList(fromList);
}).catch(
function (error) {
console.log(error);
});
let newList=[];
let newListLink=[];
let ofList=fromList;
ofList.map((item)=>{
newList.push(item.gender);
newListLink.push(item.link);
});
setList(newList);
}
// call the function
fetchData();
});
let onChange=(value,tag)=>{
if(tag==='gender'){
setCurrentValue(value);
let newList=[];
fullList.map((item)=>{
if(item.gender.startsWith(value)){
newList.push(newList.push(item.gender));
}
});
setList(newList);
}
}
let handleSubmit=async(event) => {
event.preventDefault();
await axios.post(
'http://localhost:8080/gender',gender)
.then(res => {
let errors=decrypt(res.data);
setError(errors.genderError);
}).catch(
function (error) {
console.log(error);
});
};
return (<div>
<form action={handleSubmit} >
genderName:<Autocomplete list={list} onChangeValue={onChange}/>
<div>{error}</div>
<input type="submit" value="Submit" />
</form>
</div>);
}
export default Gender;
In React component :
I am setting
const object = {
name: this.state.Name,
place: this.state.Place
}
callBackend(object).then(validateResult => {
if (validateResult.valid === true) {
this.setState({status: 'saved'});
} else {
this.setState({status: 'error'});
}
}
--------------
// this call goes to service
import axiosInstance from "../Axios";
export const callBackend = (object) =>
axiosInstance.post(`/employee/saveInfo`, { object }).then(res => {
console.log(res);
return res.data;
});
----------------
In java:
#PostMapping(path = "/saveInfo")
public ResponseEntity<List<object>> saveInfo(#RequestBody Object o) {
System.out.println(o.getName);// getting java.lang.NullPointerException
}
Solution is no brackets around object.
export const callBackend = (object) =>
axiosInstance.post(/employee/saveInfo, object).then(res => {
console.log(res);
return res.data;
I am really struggling with this
I have an action controller like this:
[HttpPost]
[Route("api/SiteCollections/SetSiteCollectionActive")]
public async Task<IHttpActionResult> SetSiteCollectionActive(string siteCollectionUrl)
{
var siteCollectionsStore = CosmosStoreFactory.CreateForEntity<TenantManagementWebApi.Entities.SiteCollection>();
var allSiteCollections = await siteCollectionsStore.Query().Where(x => x.Title != null).ToListAsync();
foreach (TenantManagementWebApi.Entities.SiteCollection sc in allSiteCollections)
{
sc.Active = false;
await siteCollectionsStore.UpdateAsync(sc);
}
var siteCollection = await siteCollectionsStore.Query().FirstOrDefaultAsync(x => x.Id == siteCollectionUrl);
if (siteCollection == null)
{
return NotFound();
}
siteCollection.Active = true;
var result = await siteCollectionsStore.UpdateAsync(siteCollection);
return Ok(result);
}
and from a reactjs application, I am trying to do the following:
// rowSelection object indicates the need for row selection
const rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
if(selectedRows[0].Url != undefined){
console.log(selectedRows[0].Url);
const options = {
method: 'post'
};
adalApiFetch(fetch, "/SiteCollections/SetSiteCollectionActive?siteCollectionUrl="+selectedRows[0].Url.toString(), options)
.then(response =>{
if(response.status === 200){
Notification(
'success',
'Site Collection set to active',
''
);
}else{
throw "error";
}
})
.catch(error => {
Notification(
'error',
'Site Collection not activated',
error
);
console.error(error);
});
}
},
getCheckboxProps: record => ({
type: Radio
}),
};
return (
<Table rowSelection={rowSelection} columns={columns} dataSource={this.state.data} />
);
However, I always get this error:
everything seems correct
Route Config
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
So, currently I'm working on internship React (MERN) app, which is a simple to-do list with ability to create, delete and edit todos. I will post some code from it, but you also can look at the full code on GitHub: https://github.com/Wonderio619/magisale-internship-todo
The next task is connecting my app to MongoDB. I have some "boilerplate" code - I alredy set up connection with MongoDB, also have Express router with routes like get all todos list, send todo to database, update todo with id, get todo with id:
const express = require("express");
const router = express.Router();
let Todo = require('../models/model')
// get all todo list with id
router.get('/', function (req, res) {
Todo.find()
.then((todos) => res.json(todos))
.catch((error) => res.send(error))
})
// send todo to database
router.post('/', function (req, res) {
let todo = new Todo();
todo.titleText = req.body.title;
todo.todoText = req.body.body;
todo.save(function (err) {
if (err)
res.send(err);
res.send('Todo successfully added!');
});
})
// get todo with id
router.get('/:todoId', function (req, res) {
Todo.findById(req.params.todoId)
.then(foundTodo => res.json(foundTodo))
.catch(error => res.send(error));
})
// updates todo with id
router.put('/:todoId', function (req, res) {
Todo.findOneAndUpdate({ _id: req.params.todoId }, req.body, { new: true })
.then((todo) => res.json(todo))
.catch((error) => res.send(error))
})
// deletes todo with id
router.delete('/:todoId', function (req, res) {
Todo.remove({ _id: req.params.todoId })
.then(() => res.json({ message: 'todo is deleted' }))
.catch((error) => res.send(error))
})
module.exports = router;
These routes used when corresponding methods from todo app are called:
import React, { Component } from 'react';
import './ToDo.css';
import Logo from './assets/logo.png';
import ToDoItem from './components/ToDoItem';
import AppBar from './components/AppBar';
import Popover from './components/Popover';
import { connect } from 'react-redux';
class ToDo extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
title: '',
todo: '',
};
};
componentDidMount = () => {
fetch("/api/todos")
.then(data => data.json())
.then(res => this.setState({ list: res.data }));
console.log(this.state.list)
};
createNewToDoItem = () => {
fetch("/api/todos", {
method: "post",
headers: new Headers({
"Content-Type": "application/json"
}),
body: JSON.stringify({
title: this.state.title,
body: this.state.todo
})
})
.catch(err => {
console.error(err);
});
if (this.state.title !== '' & this.state.todo !== '') {
this.props.createTodoItem(this.state.title, this.state.todo);
this.setState({ title: '', todo: '' });
}
};
handleTitleInput = e => {
this.setState({
title: e.target.value,
});
};
handleTodoInput = e => {
this.setState({
todo: e.target.value,
});
};
editItem = (i, updTitle, updToDo) => {
const modifyURL = "/api/todos/" + i;
fetch(modifyURL, {
method: "put",
headers: new Headers({
"Content-Type": "application/json"
}),
body: JSON.stringify({
title: updTitle,
todo: updToDo
})
})
.then(resp => {
if (!resp.ok) {
if (resp.status >= 400 && resp.status < 500) {
return resp.json().then(data => {
let error = { errorMessage: data.message };
throw error;
});
} else {
let error = {
errorMessage: "Please try again later. Server is not online"
};
throw error;
}
}
return resp.json();
})
.then(newTodo => {
let arr = this.props.list;
arr[i].title = updTitle;
arr[i].todo = updToDo;
this.setState({ updateList: true });
});
};
deleteItem = indexToDelete => {
const deleteURL = "/api/todos/" + indexToDelete;
fetch(deleteURL, {
method: "delete"
})
.then(resp => {
if (!resp.ok) {
if (resp.status >= 400 && resp.status < 500) {
return resp.json().then(data => {
let error = { errorMessage: data.message };
throw error;
});
} else {
let error = {
errorMessage: "Please try again later. Server is not online"
};
throw error;
}
}
return resp.json();
})
.then(() => {
this.props.deleteTodoItem(indexToDelete);
});
};
randId() {
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10);
}
eachToDo = (item, i) => {
return <ToDoItem
key={this.randId()}
title={item.title}
todo={item.todo}
deleteItem={this.deleteItem.bind(this, i)}
editItem={this.editItem.bind(this, i)}
/>
};
render() {
const { list } = this.props;
return (
<div className="ToDo">
<img className="Logo" src={Logo} alt="React logo" />
<AppBar />
<div className="ToDo-Container">
<div className="ToDo-Content">
{list.map(this.eachToDo)}
</div>
<div>
<Popover
toDoValue={this.state.todo}
titleValue={this.state.title}
titleOnChange={this.handleTitleInput}
toDoOnChange={this.handleTodoInput}
addHandler={this.createNewToDoItem}
/>
</div>
</div>
</div>
);
}
}
const mapStateToProps = (state) => {
return {
list: state.list
}
}
const mapDispatchToProps = dispatch => {
return {
deleteTodoItem: id => {
dispatch({ type: "DELETE_TODO", id: id });
},
createTodoItem: (title, todo) => {
dispatch({ type: "CREATE_TODO", title: title, todo: todo });
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(ToDo);
Note that "list" array from state is not really used, bacause I have initial list state in Redux state here( it may be implemented bad, but it is anyway):
const initState = {
list: [
{
title: 'Cup cleaning',
todo: "Wash and take away the Kurzhiy's cup from WC"
},
{
title: 'Smoking rollton',
todo: 'Do some rollton and cigarettes'
},
{
title: 'Curious dream',
todo: 'Build a time machine'
}
],
};
const rootReducer = (state = initState, action) => {
switch (action.type) {
case "DELETE_TODO":
let newList = state.list.filter((todo, index) => action.id !== index)
return {
...state,
list: newList
}
case "CREATE_TODO":
const title = action.title;
const todo = action.todo;
let createdList = [
...state.list,
{
title,
todo
}
]
return {
...state,
list: createdList
}
default:
return state;
}
}
export default rootReducer;
So, now I need some help - if I understand everything right, my list state should now be stored inside MongoDB database. But currently it is in Redux, how should I switch from current state implementation to MongoDB properly ?
Also I understand that my MongoDB implementation is far from perfection, I'm just newbie to this, but I need to solve following problems:
1) I tried to get all todos from database in ComponentDidMount method and save it in array, but console.log always show that array is empty smth definitely wrong there.
2) Also connection with database is not really set up, because in general I can only add todos to database, but delete or edit functions does not work, because I'm little stuck about how to implement this index stuff, should I use ObjectId property from MongoDB or should I pass indexes from my main component to database, and how ?
Also any global recommendations regarding proper mongodb implementaion and suggestions or fixes to my code will be greatly appreciated :)
It's not res.data but res that you should inject in your state. res.data is undefined so it won't update the state.list.
componentDidMount = () => {
fetch("/api/todos")
.then(data => data.json())
.then(jsonData => {
console.log('jsonData --', jsonData)
console.log('jsonData.data is empty!', jsonData.data)
this.setState({ list: jsonData })
});
};
1- To be able to update, you're sending an id. You may create id's in your db if that's the way you want to find your todos.
Please note that _id is different from id.
_id mongodb's ObjectId, it is not of type integer but of type ObjectId.
id is just a regular field that you created that is called id.
NB: Your req.params.todoId is an integer. While ObjectId is of type ObjectId! So you won't be able to query one with the wrong type.
var todoSchema = new Schema({
id: Number,
titleText: String,
todoText: String
});
2- Get your todo and update it thanks to the id. If it does not exist, it will be created thanks to the upsert option. Don't forget to cast in order to match your schema. title: req.body.title won't work because you defined it as titleText in your schema.
// updates todo with id
router.put('/:todoId', function (req, res) {
const data = {
titleText: req.body.title,
todoText: req.body.todo
}
Todo.findOneAndUpdate(
{ id: req.params.todoId }, // the query
{ $set: data }, // things to update
{ upsert: true } // upsert option
).then((todo) => res.json(todo))
.catch((error) => res.send(error))
})
I'm trying to log in in my API, save the token and go to the next page. So, I solved to use the AsyncStorage to save the token, and after this, send the token in header to get the data. See the Login.js class:
Login.js
export default class Login extends React.Component {
constructor (props) {
super (props);
this.state = { tokenValue: '' }
}
updateTokenValue= (tv) => { this.setState({tokenValue : tv}); }
async saveToken() {
try { await AsyncStorage.setItem('tokenvalue', this.updateTokenValue(this.state.tokenValue)); }
catch (error) { console.error('[APIREQUEST] AsyncStorage error: ' + error.message); }
}
onLogin() {
axios.post('http://my-api-url/login', {
'credential': this.state.txtInputUser,
'password': this.state.txtInputPassword
})
.then((response) => {
if(response.status != 200){
Alert.alert('ERROR’, ‘USER or PASSWORD INVALIDATE’);
} else {
console.log("Login success”);
console.log(response.data.token+" | Status: "+response.status);
saveToken(response.data.token);
// open the next screen
Actions.searchproduct ({
userID: 0,
});
}
})
.catch(function (error) {
console.log('Error: '+error)
return;
});
}
render() {
return (
<View style={styles.container}>
<TextInput style={styles.inputFields} value={'mobi-dev#blendmobi.com'} onChangeText={txtInputUser => this.setState({txtInputUser})} placeholder={'Usuário'} placeholderTextColor={'#9E9E9E'}/>
<TextInput style={styles.inputFields} value={'Blend#03'} onChangeText={txtInputPassword => this.setState({txtInputPassword})} placeholder={'Senha'} placeholderTextColor={'#9E9E9E'}/>
<MyButton w="100%" h={55} mt={5} as="stretch" so={0.1} ai="center" bg="#212121" tc="#F5F5F5" fs={22} t="LOGIN" onPress={() => this.onLogin()}/>
</View>
</View>
);
}
}
and my SearchProduct class:
SearchProduct.js
// imports
export default class SearchProduct extends React.Component {
constructor(props) {
super(props);
this.state = { tokenValue: '', };
}
getTokenValue= (tv) => { this.setState({tokenValue : tv}); }
componentDidMount() {
var valueToken = '';
try{
const token = AsyncStorage.getItem('tokenvalue');
if (token != null) {
valueToken = token;
console.log('[SEARCHPRODUCT] Token saved: '+valueToken);
} else {
console.log('[SEARCHPRODUCT] Token empty’);
}
} catch(error) {
console.log('[SEARCHPRODUCT] ERROR TO GET THE TOKEN: '+error);
}
axios.get('http://my-api-url/listdata’, {
headers: {
Authorization: 'Bearer '.concat(valueToken)
},
})
.then((response) => {
console.log(response);
})
.catch((e) => {
console.log('ERROR TO SYNC: '+e)
});
}
// …
}
And in the console of the browser, the data, that is returned to me is: [object Object]
OBS: it's the model of the JSON that's returned to me:
{
"id": "5b048159952a12c06c1d4305",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYmFja29mZmljZSIsImRlbGV0ZWQiOmZhbHNlLCJ1cGRhdGVkQXQiOiIyMDE4LTA1LTI4VDAwOjM4OjM2LjEzN1oiLCJfaWQiOiI1YjA0ODE1OTk1MmExMmMwNmMxZDQzMDUiLCJuYW1lIjoiTW9iaSIsInN1cm5hbWUiOiJEZXYiLCJlbWFpbCI6Im1vYmktZGV2QGJsZW5kbW9iaS5jb20iLCJfc3RvcmVJZCI6IjVhZjQ2MDRlMzMxZTBhMjRjNDM3YWE0ZSIsImlhdCI6MTUyNzQ2NzkxNn0.Yb-ImCWAzv88wtQE65p1Ejv7q8n4rmGsmIsj_DCiSfI"
}
You can change the saveToken function like below
async saveToken() {
try {
await this.updateTokenValue(this.state.tokenValue);
await AsyncStorage.setItem('tokenvalue', this.state.tokenValue);
}
catch (error)
{
console.error('[APIREQUEST] AsyncStorage error: ' + error.message);
}
}