Searchbar in react to call table of data - javascript

I'm trying to create a searchbar in react that creates a table of data from an API inside the current view.
async function handleSearch() {
console.log("searching...", searchRef.current?.value);
setMessage("Searching...");
var headers = {
"Content-Type": "application/x-www-form-urlencoded",
"auth-token": token,
};
fetch(
"http:"..
{
method: "GET",
headers: headers,
}
)
.then((response) => {
setMessage("");
if (response.status !== 200) {
console.log("erROR", response);
return null;
} else {
console.log("success", response);
this.searched = true;
let productList = response.json()
return productList;
}
})
.then((responseData) => {
console.log("responseData", responseData);
// setting resonseData to productList
setProductList(responseData);
});
}
For some reason this is ridiculously hard to get working.
I would imagine the code above would work and fill the table with the correct array, but is it not.
The JSON response is like this and works properly in the console with the search component currently.
Any idea on how to solve this issue?

It seems you need to add productList as state variable like below.
// We need to initialize with empty array. Otherwise while rendering component for the first time it will try to access map of undefined(productList).
const [productList,setProductList] = useState([]);
// And then in your fetch call you can store data inside productList
fetch(
"http://localhost:5000/adverts/mwap?searchTerm=" +
encodeURIComponent(searchRef.current.value),
{
method: "GET",
headers: headers,
}
)
.then((response) => {
setMessage("");
if (response.status !== 200) {
console.log("erROR", response);
return null;
} else {
console.log("success", response);
this.searched = true;
let productList = response.json()
return productList;
}
})
.then((responseData) => {
console.log("responseData", responseData);
// setting resonseData to productList
setProductList(responseData);
});

Related

How to push response data redux saga

so the idea is everytime i click the button it will dispatch my action,and i want to push my response data into an array, but it always overwrite an exising array, how do i fix it?
this is my code
function searchApiPhoto(param, page) {
const config = {
headers: {
Authorization: 'api-token',
},
}
return axios
.get(apiurl, config)
.then((res) => {
let data = []
// let result = [];
// console.log("data :", res.data.results);
// data = [...res.data.results];
// data.push(...res.data.results);
data.push(res.data.results)
console.log('datas =>', data)
// return result;
return res.data.results
})
.catch((err) => {
console.log(err)
})
}

Axios and response data set split to multiple arrays

I'm trying to get data from an API using axios command like
function fetchData(apiURL){
let data = [];
let options = {
method: "GET",
url: apiURL,
headers: {
"Access-Control-Allow-Origin": "*"
},
credentials: "include"
};
axios(options)
.then(response => {
data = response.data;
console.log(data);
})
.catch(function (error) {
console.log("System error : " + error);
});
return data;
}
but that will produce sets of arrays which will store arrays of JSONs from response.data in count of 100 per array set.
I haven't had problem using fetch() to retrieve all data. How I can get similar response of one large array of JSON objects instead of a split?
PS.
I have triggered that function in the
componentDidMount() {
const apiURL = process.env.REACT_APP_API;
let tableData = fetchData(apiURL);
console.log("DATA " + JSON.stringify(tableData));
this.setState({tblData : tableData});
}
Axios requests are asynchronous and return promises, so you need to adjust your example a bit so that your function returns a promise.
/**
* #return {Promise<T>}
*/
function fetchData(apiURL){
const options = {
method: "GET",
url: apiURL,
headers: {
"Access-Control-Allow-Origin": "*"
},
credentials: "include"
};
return axios(options)
.then(response => {
return response.data;
})
}
Now, when you consume this API do so asynchronously.
function somethingThatUpdatesThatUI() {
fetchData("/api/foo/bar")
.then((data) => {
//perform updates to UI or state here
})
.catch((err) => {
//alert the users that an error has happened here
})
}
You can update the componentDidMount function:
componentDidMount() {
const apiURL = process.env.REACT_APP_API;
fetchData(apiURL).then(data => {
console.log(data ${JSON.stringify(tableData)})
this.setState({tblData : data});
})
}

Problem with nested fetch request in React

New to React, I'm currently trying to create a data table with data from an API.
I want to have a first fetch, and then run another with response from the first (id) in order to complete my table.
Here is my code :
class HomePage extends React.Component {
constructor(props) {
super(props);
this.state = {
user: {},
data: []
};
}
componentDidMount() {
this.setState({
user: JSON.parse(localStorage.getItem('user'))
}, function () {
this.loadAllObjectsInfo()
});
}
// Fetch all object info in order to fill the table
loadAllObjectsInfo() {
const requestOptions = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'bbuser': this.state.user.userId,
'bbtoken': this.state.user.secret
},
};
fetch('https://xxxxx/api/objects', requestOptions)
.then(response => response.json())
.then((data) => {
this.setState({ data: data })
})
}
With this code, I have the data I want to render my table but I need to run another fetch to get other info with the id coming from the first request.
How can I do that nested fetch request ?
Thanks a lot,
Matthieu
You can easily manage this with async/await:
async loadAllObjectsInfo() {
const requestOptions = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'bbuser': this.state.user.user
'bbtoken': this.state.user.secret
},
};
let response = await fetch('https://xxxxx/api/objects', requestOptions);
let data = await response.json();
// here is another fetch - change to fit your request parameters (this is just example)
let info = await fetch('https://xxxxx/api/objects/' + data.id);
this.setState({ data });
}
You can read more about async function.
#JourdanM, you should return a new fetch request from one of the then handlers. I've made a simple snippet for you. There are no data validators and spinners. This is a simple showcase. =)
A fetch request returns a promise, and you can chain promises by simply returning them from the then handlers. Here is a good article about it, it has great examples: https://javascript.info/promise-chaining
function fetchUser (user) {
return fetch(`https://api.github.com/users/${user.login}`)
}
class User extends React.Component {
state = {
user: null
}
componentDidMount () {
fetch("https://api.github.com/users")
.then(response => response.json())
.then(users => fetchUser(users[0]))
.then(response => response.json())
.then(user => {
this.setState({user})
})
}
render () {
return (
<div>
<pre>{JSON.stringify(this.state.user, null, 2)}</pre>
</div>
)
}
}
ReactDOM.render(<User />, document.querySelector("#root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
You can write the code as below.
fetch('https://xxxxx/api/objects', requestOptions)
.then(response => response.json())
.then((res1) => {
fetch('https://xxxxx/api/objects', requestOptions)
.then(response => response.json())
.then((res2) => {
this.setState({ data: res2 });
});
});
Hope this will work for you!
You can also use axios like below
axios.post(url, data, header).then(res => {
if(res.status === 200){
console.log('1st data')
axios.post(url, data, header)
.then(response => {
if (response.status === 200) {
console.log('2nd data')
} else {
console.log('2nd error')
}
});
}else{
console.log('1st error')
}
});

Call Function(that render component) in async Function

Good day everyone.
I have problem with this piece of code:
It's 2 function:
1.renderModal() - it's responsible for rendering ModalSuccess at the moment where data sucesfully will be added to databbase (to inform user about correctly fill form.
Component ModalSuccess when call it's render modal.
2.submitToServer - it's sending all data from redux-form to API.
In end of try, i trying call function renderModal.
How can i make it correctly?
function renderModal() {
return (
<div>
<ModalSuccess/>
</div>
);
}
//async function send to server
export async function submitToServer(values) {
//FUND
try {
let response = await fetch('endpoint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...authHeader()
},
body: JSON.stringify(values),
});
let responseJson = await response.json();
return responseJson;
renderModal();
} catch (error) {
console.error(error);
}
I call submitTo server in 2 places:
1.
export var submit =(values) =>{
let isError =false;
if (isError) {
// throw new SumissionError(error);
} else{
return submitToServer(values)
.then(data =>{
if (data.errors) {
console.log(data.errors);
throw new SubmissionError(data.errors);
} else{
console.log(values)
console.log('server added data to database');
}
});
}
}
2.
<form onSubmit={handleSubmit(submitToServer)}>
I think you can restructure your code a bit better. Instead of returning the modal you can just mount the modal once and control its visibility leveraging the state.
Take a look at how I think your component should be structured.
class Comp extends React.Component {
state = {
isOpen: false
};
submitToServer = async values => {
try {
let response = await fetch("endpoint", {
method: "POST",
headers: {
"Content-Type": "application/json",
...authHeader()
},
body: JSON.stringify(values)
});
let responseJson = await response.json();
this.setState({ isOpen: true });
return responseJson;
} catch (error) {
console.error(error);
}
};
render() {
/* your component */
<ModalSuccess isOpen />;
}
}
As it stands your renderModal() invocation will never register since you are returning once the response it has been returned.
What you'd need to is something like this:
let responseJson = await response.json();
if (responseJson) {
renderModal();
}

localstorage.getitem('key') sometimes returns null - in a react app

this is a very weird problem! I'm trying to build a login form which sets a JWT token in localstorage. Other forms then use that token to post requests. I can see the token in my console.log just fine, but sometimes (like 3 out of 5 times), when I am setting localstorage.getitem('idToken'), it shows as null. This behavior most noticeably happens when I remove the console.log(idToken) from my loginUser() function (code in actions.js file - given below). What am I doing wrong? my app is built using React/Redux.
action.js
export function loginUser(creds) {
const data = querystring.stringify({_username: creds.username, _password: creds.password});
let config = {
method: 'POST',
headers: { 'Content-Type':'application/x-www-form-urlencoded' },
body: data
};
return dispatch => {
// We dispatch requestLogin to kickoff the call to the API
dispatch(requestLogin(creds));
return fetch(BASE_URL+'login_check', config)
.then(response =>
response.json().then(user => ({ user, response }))
).then(({ user, response }) => {
if (!response.ok) {
// If there was a problem, we want to
// dispatch the error condition
dispatch(loginError(user.message));
return Promise.reject(user)
} else {
localStorage.setItem('idToken', user.token);
let token = localStorage.getItem('idToken')
console.log(token);
// if I remove this log, my token is returned as null during post.
dispatch(receiveLogin(user));
}
}).catch(err => console.log("Error: ", err))
}
}
here's my POST request:
import axios from 'axios';
import {BASE_URL} from './middleware/api';
import {reset} from 'redux-form';
let token = localStorage.getItem('idToken');
const AuthStr = 'Bearer '.concat(token);
let headers ={
headers: { 'Content-Type':'application/json','Authorization' : AuthStr }
};
export default (async function showResults(values, dispatch) {
console.log(AuthStr);
axios.post(BASE_URL + 'human/new', values, headers)
.then(function (response) {
console.log(response);
alert("Your submit was successful");
//dispatch(reset('wizard'));
}).catch(function (error) {
console.log(error.response);
alert(error.response.statusText);
});
});
This GET request works everytime, BTW:
getHouses = (e) => {
let token = localStorage.getItem('idToken') || null;
const AuthStr = 'Bearer '.concat(token);
axios.get(BASE_URL + 'household/list', { headers: { Authorization: AuthStr } }).then((response) =>
{
let myData = response.data;
let list = [];
let key =[];
for (let i = 0; i < myData._embedded.length; i++) {
let embedded = myData._embedded[i];
list.push(embedded.friendlyName);
key.push(embedded.id);
}
this.setState({data: list, key: key});
})
.catch((error) => {
console.log('error' + error);
});
}
I'm at my wit's end! Please help!
The localStorage.setItem() is a asynchronous task, and sometimes you run let token = localStorage.getItem('idToken') just after the setItem will fail, so you get a null, so please put the getItem operation some later, have a try, it will be different :
setTimeout(function() {
let token = localStorage.getItem('idToken');
dispatch(receiveLogin(user));
}, 50);
Move your token logic (i.e. localStorage.getItem('idToken');) inside the exported function and it should work
export default (async function showResults(values, dispatch) {
let token = localStorage.getItem('idToken');
const AuthStr = 'Bearer '.concat(token);
let headers ={
headers: { 'Content-Type':'application/json','Authorization' : AuthStr
}
};
axios.post(BASE_URL + 'human/new', values, headers)...
There can't be a case where you set a key value in localstorage and then it returns you null, immediately in the next line.
localStorage.setItem('idToken', user.token);
let token = localStorage.getItem('idToken');
This will only happen if your user.token value is null.
Maybe the case here is your thennable function not returning value to your next then like this:
....
.then(response =>
// return response to your next then function
// this will be passed to next then function as params
return response.json();
).then(({ user, response }) => {
....
Make a function whose return the value or a default value
const [hideTyC, setHideTyC] = useState(false);
const loadTyCFlag = (): any => {
if (
localStorage.getItem("tyc") !== null ||
localStorage.getItem("tyc") !== undefined
) {
return localStorage.getItem("tyc") || false;
}
};
useIonViewDidEnter(() => {
hideTabBar();
setHideTyC(loadTyCFlag());
});

Categories

Resources