The fetching is not going smoothly. I want images to show up at the same time. Here is how I have done it:
const [isLoading, setIsLoading] = useState(false)
useEffect(()=>{
setIsLoading(true)
fetch(url).then(res=>res.json()).then(data=>{
setPhoto(data)
setIsLoading(false)
})
},[url])
And then, I check, if isLoading is true, then I return "Loading" text. Else, the code should return the images page:
return (
<div className="App">
<header>.....
{isLoading?<p className={'text-5xl mt-11'}>Loading...</p>:<div className={'flex flex-wrap space-x-2 justify-around '}>
{photos?photos.hits.map((photo, index)=>{
return <img className={'m-5 h-80 rounded-2xl'} onClick={handleClickOnPicture} key={photo.webformatURL} src={photo.webformatURL}/>
}):""}
Your images loading actually happens in 2 steps:
You fetch your image URL's (data stored in photo state), for which you properly handle isLoading state
You display the <img> elements with src attribute populated with URL's from step 1; but this is only the point where the browser knows of these new media resources, and starts fetching their content: this explains why you see your images appearing 1 by 1; the <img> element is there, but its actual content is still being fetched
To force the browser fetching your images content before you display them, the classic solution is to create an Image (HTMLImageElement) and to populate their src attribute. The browser starts requesting their content even if these objects are not actually inserted into the DOM.
Then you need to know when these images have finished loading in the background. For that, we use the onload property on the <img>, which adds an event listener that is called when the content has been retrieved (and cached) by the browser.
Once all images have finished loading, we can insert them into the DOM (possibly through new <img> elements, provided that they re-use the same URL's), and the browser will use its cached data to display them "instantly".
See e.g. How to preload images in React.js? for how to implement step 2 in details with React.
Related
I want to scrape this link : https://www.magicbricks.com/property-for-sale/residential-real-estate?bedroom=&proptype=Multistorey-Apartment,Builder-Floor-Apartment,Penthouse,Studio-Apartment&cityName=Mumbai for the links for each property.
The link to the individual pages for each property is not in the HTML source code. The opening of the page instead is linked to an event. How do I get the links to the page that opens using Scrapy and Playwright?
Each website is different and needs to be treated differently. Usually the journey starts from the element panel of the page.
Upon taking a closer look at the elements panel of the url you have shared, we can see each card is inside a div and the div also has a script tag with a json. The json indeed has the URL you were looking for.
Here is the code to extract the URLs that you can run inside the page.evaluate function.
await page.evaluate(async () => {
const urls = [];
// parent card elements
var cardElements = [...document.querySelectorAll('[class="mb-srp__list"]')];
for(let cardElement of cardElements) {
// get nested script tag inside each card element that contains the url
const script = cardElement.querySelector('script');
// but the content of the tag is a string, so we need to parse
const cardJSON = JSON.parse(script.innerHTML);
// finally save whatever data we want
urls.push(cardJSON.url);
}
return urls;
});
Here is a shorter version of the code that can go inside page.evaluate,
[...document.querySelectorAll('[class="mb-srp__list"]')].map(card=>JSON.parse(card.querySelector('script').innerHTML).url)
Using next.js with SSR I'm having a strange problem.
My website renders as expected server-side and is served to the client with styles. There are no surprises here when I'm visiting the website on a laptop everything looks as expected.
However, when I visit the website on a mobile device (or simulated smaller window), the first render is rendered with the same styles as my desktop styles, even though my mobile media query returns true
I'm using https://github.com/wintercounter/use-breakpoint for most of my media queries.
Which looks like this:
const { 'isMobile-': isMobileMinus } = useBreakpoint()
and my layouts etc. should change based on whether isMobileMinus is true or false.
For example, this antD component is supposed to switch from horizontal to vertical if it's a mobile device.
<Space size="middle" direction={isMobileMinus ? 'vertical' : 'horizontal'}>
What is really interesting is that when I render the webpage in a small window the size of a mobile device I can console log isMobileMinus to be true, but my components do not update until I either resize the window (and it's true again) or I navigate to another page and back.
It acts as if isMobileMinus was false, but only for that specific component.
I can even render the value of isMobileMinus in the component and it will render true on first render, but the components I have acts as if it was false until I make another update.
I find this very strange as the component is clearly re-rendering with the correct value, but it does not update the styles of the components that were styled via SSR?
This problem is not just limited to the above hook based media queries but also other things.
For example I have 2 buttons that are rendered on SSR called "login" and "Signup" which are supposed to be white and green respectively.
However when the webpage renders if the user is already logged in. It should render 2 new buttons called "Log out" and "Dashboard" which are red and blue respectively.
But somehow on first render. The text of these buttons will update to logout and dashboard, but the styles of the buttons will be white and green (incorrect).
These are completely different components, but next.js still keeps the old styles?
if (loggedIn) {
return (
<Space>
<LogoutButton onClick={handleLogout} />
<DashboardButton onClick={handleDashboardClick} />
</Space>
)
}
return (
<Space>
<LoginButton />
<SignupButton onClick={showSignup} />
</Space>
)
There seems to be some really strange thing with next.js where it will update the content of the HTML, but refuses to update the CSS when a component is re-rendered on the client-side.
Anyone knows how to fix this?
I tried making a copy like suggested here: How to immediately re-render client-side using React + NextJS after initial server-side render? which seems to be a similar issue.
const breakpoints = useBreakpoint()
const copy = lodash.cloneDeep(breakpoints)
const { 'isMobile-': isMobileMinus } = copy
console.log('🔈 ~ isMobileMinus', isMobileMinus)
But that did not work for me either.
I'm on "next": "11.0.1",
I found 1 solution but it feels more like a hack than a solution.
If I wrap my components in process.browser && (<Component />) then the component will not render during SSR, and only render client-side.
This causes the component to render correctly when the webpage is loaded.
But of course I would ideally like to take advantage of SSR, and just update the styles client side :(
Note that this hack also causes console errors, so it is definitely not recommended. It seems like the use-breakpoint library is incompatible with SSR frameworks.
I am new in React. I am attempting to make a live feed from my wordpress site. I am having trouble rendering the images associated with each article.
In the code below I log the mediaSRC variable which I am storing the url of the image. When logging this the proper URL outputs to console. However when I try to create my Post object later on after the if statement, the mediaID is = to "NO IMAGE"
When I am rendering the POST the html img is showing img src="NO IMAGE"
<div className="main-feed">
{posts.map(function(post){
//mediaSRC is eventually going to by my <img src >
var mediaSRC ="NO IMAGE";
//post.featured_media will access the media ID of the image
var media = post.featured_media;
// if there is no image set mediaSRC to this string
if (post.featured_media ==0){
mediaSRC="MEDIA ID IS ZERO";
}
// if there is an image, set mediaSRC to the url of image
else{
j.ajax(React_Theme_Resource.url + "/wp-json/wp/v2/media/" +media)
.done(function(data){mediaSRC = data.guid.rendered; console.log(mediaSRC)})
.fail(function(){console.log("FAIL")})
.always(function(){})
}
//Create Post object NOTE : working without images
return <Post post={post} mediaID={mediaSRC} key={post.id} />
})}
</div>
You are getting your image via an ajax request, but the component is not updated with the new image source. There are a couple of issues here.
It is a bad practice to make ajax request in your render method. The best place for them (if you are not using Flux, Redux or other state management library) is in the constructor.
Secondly, you need to use .setState() (again, if you are using react state to manage the state of the component and the app) method to add the new image source to the component.
You can read more about react state here: https://facebook.github.io/react/docs/state-and-lifecycle.html
I'm implementing an infinite scroll on Meteor in order to display a grid of pictures linked to a large collection.
When the user is at the end of the page I subscribe to more elements and I increase the number of pictures displayed (through my template.helper).
//SERVER
Meteor.publish('generalMusics', function(limit){
return Musics.find({}, {limit: limit});
});
//CLIENT: when the template is created and when the limit of data increases
//it subscribes again
Template.t_elementSubHeader.onCreated( function() {
Session.set('reqLimit',50);
var self = this;
//Everytime reqLimit changes I redo the subscribe
this.autorun(function(){
self.subscribe('generalMusics', Session.get('reqLimit'));
});
//CLIENT: more elements are sent to the template when reqLimit increases
Template.t_elementSubHeader.helpers({
data: function() {
return Musics.find({}, {limit : Session.get('reqLimit')});
}
});
//Also on client, when the user reach the bottom of the page
Session.set('reqLimit',Session.get('reqLimit')+50);
It works well but all the template elements are re-rendering and it also takes some time to do so. It's very inconvenient for the user, I think it takes time because I'm displaying pictures and not text (we already compress the pictures to a minimum size).
The problem is due to the subscribe that rerender all the template elements.
How can I do to just add the new elements and prevent the re-rendering of the already displayed elements when I subscribe ?
My app will be on mobile devices so I can't subscribe to a lot of elements and then just increase the limit in the template helper.
Finally I got it, i've added some code in the html to wait the subscription to be ready and I forgot about it.
I removed:
{{#if Template.subscriptionsReady}}
{{> Template.dynamic template="t_elementList" data=tabData}}
{{/if}}
Infinite scroll is working like a charm.
I'm writing a WinJS app that takes an HTML fragment the user has copied to the clipboard, replaces their
Later, when I go to display the .html, I create an iFrame element (using jQuery $(''), and attempt to source the .html into it, and get the following error
0x800c001c - JavaScript runtime error: Unable to add dynamic content. A script attempted to inject dynamic content, or elements previously modified dynamically, that might be unsafe. For example, using the innerHTML property to add script or malformed HTML will generate this exception. Use the toStaticHTML method to filter dynamic content, or explicitly create elements and attributes with a method such as createElement. For more information, see http://go.microsoft.com/fwlink/?LinkID=247104.
I don't get the exception if I don't base64 encoded the images, i.e. leave them intact and can display iframes on the page with the page showing images.
If I take the html after subbing the urls for base64 and run it through toStaticHTML, it removes the src= attribute completely from the tags.
I know the .html with the encoded pngs is right b/c I can open it in Chrome and it displays fine.
My question is I'm trying to figure out why it strips the src= attributes from the tags and how to fix it, for instance, creating the iframe without using jquery and some MS voodoo, or a different technique to sanitize the HTML?
So, a solution I discovered (not 100% convinced it the best and am still looking for something a little less M$ specific) is the MS Webview
http://msdn.microsoft.com/en-us/library/windows/apps/bg182879.aspx#WebView
I use some code like below (where content is the html string with base64 encoded images)
var loadHtmlSuccess = function (content) {
var webview = document.createElement("x-ms-webview");
webview.navigateToString(content);
assetItem.append(webview);
}
I believe you want to use execUnsafeLocalFunction. For example:
var target = document.getElementById('targetDIV');
MSApp.execUnsafeLocalFunction(function () {
target.innerHTML = content}
);