How can I change a source of a video in react? - reactjs

I have used a react-video component in my reactjs web application and it's working with a default source link, but when I'm using my video as a source, nothing happens.
I have searched a lot, read the documentation about react-video component, but could not solve the problem.
import {Player} from 'video-react';
<div className = 'video-container'>
<Player
playsInline
fluid={false}
src="https://media.w3.org/2010/05/sintel/trailer_hd.mp4"
width={600}
height={300}/>
</div>
I expect the new source to be working without any issues, but it never starts playing.

#Dato.Beriashvili, I have faced similar issues in default html video API, whenever i change src by anymeans video was not updated. so i have done below which fixed my issue.
useEffect(() => {
const myVideo= innerDoc.querySelector('#videoPlayer');
const mySource = innerDoc.querySelector('#source');
if (mySource && myVideo) {
mySource.setAttribute('src', videoUrl);
myVideo.load();
}
}, [videoUrl]);
whenever url changed, i'm manually loading it.

Related

Algolia: Export React Instant Search results

Is there any way to export Algolia's React Instant Search results to a CSV? I've tried using the react-csv package, but it doesn't work with Algolia's Hit Component. The package requires data as props, but the data is constantly changing since it's React Instant Search.
What I mean by constantly changing is that on page load, you're given the entire index of records found, then you can narrow down the results with the search bar or other filtering components.
I've gone down the Google rabbit hole looking for information about exporting Algolia's search results as a CSV, but I haven't found anything regarding React Instant Search—unless I completely missed it.
Has anyone tried this before? If so, could you point me in the right direction regarding documentation or examples?
Not sure if this solves your problem but one possible way is to use the StateResults widget. The StateResults widget provides a way to access the searchState and the searchResults of InstantSearch.
Here I will create a custom StateResults component in the form of a download button and then connect it using the connectStateResults connector.
I have attached a demo below as well.
For simplicity I didn't format the data to be fed into the CSV builder.
// 1. Create a React component
const StateResults = () => {
// return the DOM output
};
// 2. Connect the component using the connector
const CustomStateResults = connectStateResults(StateResults);
// 3. Use your connected widget
<CustomStateResults />
In your case something like
const StateResults = ({ searchResults }) => {
const hits = searchResults?.hits;
return (
<div>
<button>{hits && <CSVLink data={hits}>Download CSV</CSVLink>}</button>
</div>
);
};
const DownloadButton = connectStateResults(StateResults);
//in your JSX then <DownloadButton />

Display a loading text/spinner until a component is fully loaded(text,images...etc) in React

I searched for a solution like this but I just couldn't find it properly so I am asking this question if anyone can help.
This is a Sandbox that I made and the idea is something like this: I want to show a loading text until my component(let's say a whole website: including images, text.. etc..) is fully loaded, tried to make this with useEffect hook but the useEffect only shows the loading text until the component is mounted, and the hook does that, but there are things like images inside this component that aren't fully loaded yet, so this does not work the way I want. I would appreciate it if anyone knows a way to make this work, there is a lot of information on the web for making something like this with a setTimeout but I think this is a bit of a tricky/fake way to do it because the loading spinner should show depending on the speed of your ISP right? so for users with a better internet connection the loading text/spinner time will be shorter and for others, it will be longer.
Link to Sandbox
you can use the following function on your component :
document.onreadystatechange = function () {
if (document.readyState === 'complete') {
console.log("do something");
}
}
or controll all document's loading period using
switch (document.readyState) {
case "loading":
// The document is still loading.
break;
case "interactive":
// The document has finished loading. We can now access the DOM elements.
// But sub-resources such as scripts, images, stylesheets and frames are still loading.
console.log('do something')
break;
case "complete":
// The page is fully loaded.
console.log("do something");
break;
}
you can also use this function if you need it :
window.addEventListener("load", event => {
var image = document.querySelector('img');
var isLoaded = image.complete && image.naturalHeight !== 0;
console.log(isLoaded);
});
You could have a 'loading' state that is true at first and then change it's value with the onload function.
You could use it like this:
<div onload={setLoading(false)}>
<img src="..." />
<img src="..." />
<img src="..." />
</div>
Onload executes when all of it's children content has finished loading. You could read more about this at https://www.w3schools.com/tags/ev_onload.asp

How to refresh the facebook like url in reactjs (using facebook-sdk CDN)

I am using Facebook's like button as generated by facebook's like button configurator. However in order to get facebook-sdk to finish loading before the Like button, I had to use something called react-load-script and make a my own wrapper component for the like button html I got from the configurator.
my like button
class Like extends React.Component {
state = {
facebookLoaded: false
};
handleFacebookLoaded = () => this.setState({
facebookLoaded: true
});
FacebookSDK = () => <>
<div id="fb-root"></div>
<Script
async defer crossOrigin="anonymous"
url="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v3.3&appId=391623981325884&autoLogAppEvents=1"
onLoad={this.handleFacebookLoaded}
/>
</>;
render() {
return <>
<this.FacebookSDK />
{this.state.facebookLoaded
? <div class="fb-like" data-href={this.props.url} data-width="" data-layout="button_count" data-action="like" data-size="large" data-show-faces="true" data-share="true" />
: null}
</>;
}
}
In my code all the script loading stuff actually happens in App.jsx, but I moved it into one class just to show a simple version.
This part seems to work fine, the issue lies when changing the url passed to data-href.
I checked the react dom in the browser and the data-href is actually being updated properly, however this does not affect the actual url that is being used by the like button, unless I do a full page refresh. I'm assuming this has to do with how the data-href is being used by facebook-sdk. (edit: after testing I'm not sure anymore)
I've found many questions about this on Stack Overflow, however none of them seem to be based off the CDN version of facebook buttons
From what I understand, the div containing the href needs to be placed out and back into the DOM in order for the facebook-sdk to detect a change, but I don't know how to do this in react without a full page refresh. Also I'm not certain this is even the right solution.
-- Update --
I just noticed something else that seems like useful information. If I navigate to the page with the like button, then it doesn't show up. It will only show up if the page refreshes. I tested it by moving the part that loads the script into the like component (like in the example shown above) and that didn't change the behavior at all.
-- more experimenting --
I wrote an event handler that takes all the facebook related jsx out of the dom and back in (by toggling a button) However when all the code goes back into the dom (both jsx and html), the UI for the button does not come back. I'm really now sure how this is possible as I'm literally reloading the script and everything facebook related so this should be equivalent to a page refresh no?
I fixed the issue thanks to misorude. The part I was missing was calling window.FB.XFBML.parse(). I didn't realize I could access FB the same way using the CDN. If anyone is looking for a react solution here is the working code:
class Like extends React.Component {
constructor(props) {
super(props);
this.state = {
url: props.url,
}
}
handleChangePage() {
let likeBtn = document.createElement('div');
likeBtn.className = "fb-like";
likeBtn.setAttribute("data-href", this.props.url);
likeBtn.setAttribute("data-width", "");
likeBtn.setAttribute("data-layout", "button_count");
likeBtn.setAttribute("data-action", "like");
likeBtn.setAttribute("data-size", "large");
likeBtn.setAttribute("data-show-faces", "true");
likeBtn.setAttribute("data-share", "true");
let likePanel = document.getElementById("like-panel");
likePanel.removeChild(likePanel.childNodes[0]);
likePanel.appendChild(likeBtn);
window.FB.XFBML.parse(likePanel)
this.setState({ url: this.props.url });
}
componentDidMount() {
this.handleChangePage();
}
render() {
if(this.props.url !== this.state.url)
this.handleChangePage();
return <div id="like-panel">
{this.props.facebookLoaded
? <div className="fb-like" data-href={this.props.url} data-width="" data-layout="button_count" data-action="like" data-size="large" data-show-faces="true" data-share="true" />
: null}
</div>;
}
}
I moved the CDN out of this component so that it only loads the sdk once for the whole app.

Unable to display images after uploading them in react component

I want to upload multiples images then display them in browser. I wrote this code mentioned by this link.
I got the name of images displayed in place of images:
Image1.png
Image2.png
How can I fix that and if someone knows another npm module which upload and display images as a gallery I will be grateful if mentioned it to me.
Adding the property withPreview to the <ImageUploader /> gives you a preview of all "uploaded" images.
const UploadImage = props => {
const { onDrop } = props;
return (
<ImageUploader
withIcon
buttonText="Upload Image"
onChange={onDrop}
imgExtension={[".jpg", ".gif", ".png", ".gif"]}
maxFileSize={5242880}
withPreview
/>
);
};
You can see this change implemented here.
This library looks like it can achieve what you want right out the box. See the documentation for the library for more details.

onClick not being called ReactJS

Before downvoting, I've been through plenty of other solutions on SO around this same issue and can't find an answer that resolves this issue.
I'm having trouble trying to get the onClick attribute to fire off my function, here's a piece from the problematic component:
Constructor:
constructor() {
super();
this.state = {
submissionFormCount: 0
}
this.addToSubmissionFormCount = this.addToSubmissionFormCount.bind(this);
}
render:
<div className="row">
<div className="col s12 m12 l12">
<h5 onClick={this.addToSubmissionFormCount} style={beatSubmissionStyles.colorize}><span>(Plus) </span>add another beat</h5>
</div>
</div>
clickHandler:
addToSubmissionFormCount() {
alert('Here');
this.setState({
submissionFormCount: this.state.submissionFormCount++
});
}
I'm rendering the app from an Express server using 'react-dom/server'
Here's how I am rendering the component:
exports.beatSubmission = (req, res) => {
const appString = renderToString(<App type="beatSubmission"/>);
res.send(beatSubmissionTemplate({
body: appString
}))
}
I think you're only rendering your react components on the server side. The reason I think this is because of the following code you've copied:
exports.beatSubmission = (req, res) => {
const appString = renderToString(<App type="beatSubmission"/>);
res.send(beatSubmissionTemplate({
body: appString
}))
}
You're rendering the component to a string and shipping the string to the frontend as static HTML. While this will indeed give you properly rendered markup, it will result in a non-interactive app.
To have click handlers work, you also need to compile your JS, and include it for use on the frontend like this:
https://github.com/erikras/react-redux-universal-hot-example/blob/master/src/server.js#L76
renderToString(<Html assets={webpackIsomorphicTools.assets()} store={store}/>));
There are a few ways to do this. You can manually add a script file with your JS pre-packaged for the frontend in your template or you can use Webpack Isomorphic Tools.
I suspect you read a react tutorial that lead you down the isomorphic (server/client side rendered) path. You can run react on the server, the client side or both. Running it on both takes some work, but results in an app that "feels" faster.
I can't see any problem with the code. However, the only thing that comes to my mind is if you're rendering the <h5> in a function of some sort, maybe mapping and array for example. If so, you need to define var self = this in the render function before the return, then use self.addToSubmissionFormCount.
P.S. I don't recommend using onClick handler in <h5> tag
Change your h5 into an anchor tag. So replace:
<h5 onClick={this.addToSubmissionFormCount} style={beatSubmissionStyles.colorize}><span>(Plus) </span>add another beat</h5>
with:
<a onClick={this.addToSubmissionFormCount} style={beatSubmissionStyles.colorize}><span>(Plus) </span>add another beat</a>
You can style your anchor anyway you want afterwards. For example if you want to not have a cursor when hovering then add cursor: none
You should not mutate the state of react.
Change:
this.state.submissionFormCount++
To:
this.state.submissionFormCount+1

Resources