How do I get my api call to call a different file? - javascript

I am using the api http://aws.random.cat/meow and it gives me a result of
{"file": "https://purr.objects-us-east-1.dream.io/i/rEJ7q.jpg"}
The file changes every time I refresh the api call on the browser which gives me a different cat pic. For example, if I refresh it would give me a different .jpg like
{"file": "https://purr.objects-us-east-1.dream.io/i/ferbus.jpg"}
I call the api in my React app, and I want to randomize the cat pic after an onClick of a button. Unfortunately, I get the same picture back when I do my api call. I put the file in an img src, but it doesn't change when I do another api call.
componentDidMount() {
this.getCats();
}
getCats = () => {
axios.get(`http://aws.random.cat/meow`)
.then(res => {
let cats = res.data.file;
console.log(cats)
this.setState({
cats
})
})
.catch(err => console.log(err))
}
render() {
return (
<div>
<img
src={this.state.cats}
alt='cat'
/>
<button onClick={this.getCats}>
Click me
</button>
</div>
);
}
I expect to get a different file every time, but instead I get the same .jpg when I do an onClick.

Related

webshare API multiple instances on same page

Hopefuly someone can assist/direct me here.
I'm making use of the webshare API on my site. The site contains an array of posts that will have a share link. This is built using a foreach and all have unique urls to use. I want to add a share button to each of those images. I currently have it working on a singular instance but unable to get it to loop through all the share buttons.
Here is the current script:
const shareButton = document.querySelector('.share-button');
const url = document.querySelector('.post-link a').href;
shareButton.addEventListener('click', event => {
if (navigator.share) {
navigator.share({
title: 'Check out this ad I saw on ...',
url
}).then(() => {
console.log('Shared');
})
.catch(console.error);
}
});
I'm really struggling with how to get it to loop through all share buttons and not just be usable on the first instance.
Apologeis if this is simple.
For a start, you need to add a click listener to all buttons, not just the first. You can do this exclusively when the API is supported, else, you may want to hide the buttons. Here's the modified script (note that you need to get the URL of each post individually, see the comment):
const shareButtons = document.querySelectorAll('.share-button');
if ('share' in navigator) {
shareButtons.forEach((shareButton) => {
shareButton.addEventListener('click', () => {
// Get the URL from the dataset or query the DOM.
const url = shareButton.dataset(url);
navigator.share({
title: 'Check out this ad I saw on ...',
url
}).then(() => {
console.log('Shared');
}).catch(console.error);
});
});
} else {
shareButtons.forEach((shareButton) => {
shareButton.style.display = 'none';
});
}

React: Reloading the page doesn't fetch the data anymore

When I am on my home page and click on a "lesson" component, the lesson page loads, takes the id of the lesson from the url and gets the data (from a local js file) to populate the lesson page. Well, that only happens when I click from the home page. But when I'm already on the lesson page with the data populated and I reload the page, I takes the id from the url but this time the data appear "undefined"... I don't understand why it doesn't take the data as previously?
Here is my component implementation:
const Lesson = () => {
const { id } = useParams();
const [lesson, setLesson] = useState(getLesson(id));
console.log("id: ", id);
console.log("lesson: ", lesson);
return (...);
};
Here is the console when I click on my lesson component from the home page:
the console when it works
There is the console when I simply reload the lesson page: the console when it doesn't work
I tried using useEffect() with a setLesson(getLesson(id)) inside but nothing changed...
I also tried this:
if (id) lesson = getLesson(id);
But again, it didn't work... :(
getLesson() gets its data from this file called fakeLessonsService.js:
import getHipHopLessons from "./hipHopLessons";
const lessons = [...getHipHopLessons()];
export function getLesson(lessonId) {
return lessons.find((lesson) => lesson._id === lessonId);
}
The file "./hipHopLessons" simply returns an array of lesson objects.
getLesson() is only loaded on this page.
The argument to useState is only used on initial render.
You should use a useEffect to update the state if the id changes
const [lesson, setLesson] = useState({});
useEffect(() => {
getLesson(id).then(val => setLesson(val));
}, [id]);
PS. Make sure getHipHopLessons is not asynchronous
If it is async, then you must write the code like
import getHipHopLessons from "./hipHopLessons";
export async function getLesson(lessonId) {
const lessons = getHipHopLessons();
return lessons.find((lesson) => lesson._id === lessonId);
}

React how to call a method from store and from props

I'm trying to make page pagintation in my model . I've used #material-ui TablePagination . The thing is, I'm using a web service to load my data and I don't want to store all the data inside the page, so I'm using the API paging offered (send parameters to the url for the correct page) .
Now to my code :
<TablePagination
component="div"
count={props.totalTableRows}
rowsPerPage={props.rowsPerPage}
page={props.brokersListPage}
onChangePage={props.setBrokersListPage}
rowsPerPageOptions = {[props.rowsPerPage]}
/>
And the setBrokersListPage :
export const setBrokersListPage = (event, page) => {
return dispatch => {
dispatch({
type: actionNames.SET_BROKERSLIST_PAGE,
page
})
getBrokers(page)
}
}
This code doesn't work . I need the dispatch action to refresh the state of the page , and I need the getBrokers to call the web service once again with the correct info . But all this does is update the page state without updating the data.
If I use this :
export const setBrokersListPage = (event, page) => {
return getBrokers(page)
}
Then the page refreshes , but then the state doesn'
tget refreshed .
How can I achieve both ?
You have to make an API call first, then pass this data to store, connected component will update afterwards. In your code i suppose you don't use the actual data from web service.
Here is simplified example:
Promise.resolve()
.then((page) => {
store.dispatch({
type: LOADING_BROKERS
});
return Api.getbrokers(page);
//get brokers here
})
.then(() => {
store.dispatch({
type: LOADED_DATA_BROKERS,
pageinfo // or whatever
});
})

Axios PUT Request in React, Redux Not Working

So I want to make a PUT request to the server, but it doesn't want to work. I know that when making a PUT request you need an identifier(e.g id) for the resource and the payload to update with. So that is my problem.
In my form I have these props:
<div>
<DoorSettingsForm
onSubmit={this.submit.bind(this)}
item={this.props.location.state.item}
id={this.props.location.state.item._id}
/>
</div>
item - All the input fields, radiobuttons etc.
id - The identifier
onSubmit - the function that handles the submitting of all of the new data, here it is:
submit(values, id) {
this.props.updateSettings(values, id)
}
And inside of my really simple action I have this:
export function updateSettings(id, item) {
return dispatch => {
console.log('ID: ', id)
return axios
.put(`${settings.hostname}/locks/${id}`, item)
.then(res => console.log(res))
.catch(err => console.log(err))
}
}
One thing that I really don't understand is when I change the places of id and item on the first line the output of my console.log changes. When having id as the first parameter I get everything I've typed in my inputs (the changes) and when having item as the first parameter I'm getting this:
ID: function (action) {
if (action.payload) {
if (!(0, _isPromise2.default)(action.payload) && !(0, _isPromise2.default)(action.payload.promise)) {
return next(action);
}
Any help with my problem is really appriciated! Thanks for reading.
I forgot to call handleSubmit with my id:
form onSubmit={() => handleSubmit(id, item)}

Use sequelize query results inside a jquery event handler

There is an electron framework that gives you a stripped down browser to build your user interface for the desktop application. In my case, I am using jQuery for DOM navigation, Sequelize to talk to my sqlite database and a couple other libraries.
Let's say I have a text field where the user can type a movie name. My database stores a couple hundred movie names. So I would like to offer the user autocomplete suggestions.
Typically, I would use something like this to register a jQuery handler (this will echo field input back to console):
$('#movie-search-field').on('input', (event) => {
console.log(event.target.val())
})
With sequelize, you would typically have a model (say, Movie) and query it like so: Movie.findAll(). Here comes the problem:
If I register my handler like so:
Movie.findAll().then((movies) => {
$('#movie-search-field').on('input', (event) => {
/*Use movies here to build and show a suggestions list*/
})
})
then it never gets triggered. I have verified that the .then clause is entered by printing movies to console from within it.
On the other hand, if I try to query the database from inside the handler:
$('#movie-search-field').on('input', (event) => {
Movies.findAll().then((movies) => {
/*Use movies to build and show a suggestions list*/
})
})
then the handler exits before the promise is resolved and no suggestions are shown.
How could I use the database query results in my event handler?
You could just make a simple callback
$('#movie-search-field').on('input', (event) => {
getResults(function(movies) {
/* Display your movies */
})
})
function getResults(callback) {
Movies.findAll().then((movies) => {
/*Use movies to build and show a suggestions list*/
callback(movies)
})
}
So when a user types in the input box it will request the suggestions and then when it returns them it will call the function (callback) and then you can display them
Turns out I made some unrelated mistakes in my event handler code and so the approach I described above works just fine:
Movie.findAll().then((movies) => {
$('#movie-search-field').on('input', (event) => {
/*Use movies here to build and show a suggestions list*/
})
})
Also, if you are doing several database queries and would like your handler to have access to all of those, you can do:
let movies = Movie.findAll()
let tickets = Ticket.findAll()
Promise.all([movies, tickets]).then(values => {
let [movies, tickets] = values
/* register your handlers here and pass the data to them */
$("#some-selector").on('input', {movies: movies, tickets: tickets}, (event) => {
let movies = event.data.movies
let tickets = event.data.tickets
/* some event handling code that uses both movies and tickets */
})
})

Categories

Resources