React is an open-source JavaScript library that is used to develop interactive user interfaces. It is managed by Facebook and a community of individual developers and companies. React mainly focuses on developing single-page web or mobile applications. here, we will create a Youtube clone.
Modules required:
- npm
- React
- axios
$ npx install axios --save
Basic setup:
- Start a project by the following command:
$ npx create-react-app youtube-clone
- now go to youtube-clone :
$ cd youtube-clone
- Start the server- Start the server by typing the following command in the terminal :
open localhost:3000$ npm start
Basic setup
- Change directory to src and delete everything:
$ cd src && rm *
now create several index.js,app.js,YoutubeApi.js,SearchBar.js,VideoDetails.js,VideoItem.js,VideoList.js file
For styling add semantic UI CDN to index.html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css">
Edit index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
Edit App.js
import React from 'react';
import SearchBar from './components/SearchBar';
import YoutubeApi, { baseParams } from './api/YoutubeApi';
import VideoList from './components/VideoList';
import VideoDetails from './components/VideoDetails';
class App extends React.Component {
constructor(){
super();
this.state = {video: [], selectedVideo: null};
}
componentDidMount(){
this.onFormSubmit('Configure passwordless sudo for a specific user in linux itsvinayak');
}
onFormSubmit = async (term) => {
const res = await YoutubeApi.get('/search',{
params: {
...baseParams,
q: term,
}
})
this.setState({
video: res.data.items,
selectedVideo: res.data.items[0],
});
}
onVideoSelect = (video) => {
this.setState({
selectedVideo: video
});
}
render(){
return(
<div className="ui container">
<SearchBar onFormSubmit={this.onFormSubmit}/>
<div className="ui two column stackable grid">
<div className="ten wide column">
<VideoDetails video={this.state.selectedVideo} />
</div>
<div className="six wide column">
<VideoList
onVideoSelect={this.onVideoSelect}
videos={this.state.video}
/>
</div>
</div>
</div>
);
}
}
export default App;
Edit youtube-clone/src/components/VideoList.js
import React from 'react';
import VideoItem from './VideoItem';
const VideoList = ({videos,onVideoSelect}) => {
const renderlist = videos.map(video => {
return( <VideoItem onVideoSelect={onVideoSelect} video={video}/> );
});
return(
<div className="ui relaxed divided list">
{renderlist}
</div>
);
};
export default VideoList;
Edit youtube-clone/src/components/VideoDetails.js
import React from 'react';
const VideoDetails = ({video}) => {
if (!video){
return(
<div class="ui active inverted dimmer">
<div class="ui text loader">Loading</div>
</div>
);
}
const videoSrc = `https://www.youtube.com/embed/${video.id.videoId}`
return(
<div>
<div className="ui embed">
<iframe src= {videoSrc}
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
title={video.snippet.title}
allowFullScreen>
</iframe>
</div>
<div className="ui segment">
<div className="content">
<a href="{video.snippet.title}" className="header"> {video.snippet.title}</a>
<div className="description">{video.snippet.description}</div>
</div>
</div>
</div>
);
}
export default VideoDetails;
Edit youtube-clone/src/components/SearchBar.js
import React from 'react';
class SearchBar extends React.Component{
constructor() {
super();
this.state = {
term:''
};
}
onInputChange = (e) => {
this.setState({term: e.target.value})
}
onFormSubmit = (e) => {
e.preventDefault();
// call back function
this.props.onFormSubmit(this.state.term);
}
render(){
return(
<div className="ui segment search-bar">
<form onSubmit={this.onFormSubmit} className="ui form">
<div className="field">
<div className="ui red ribbon label">YouTube video search</div>
<div className="ui input icon focus" style={{marginTop:"10px"}}>
<input
value={this.state.term}
type="text"
placeholder="Search..."
onChange={this.onInputChange}
/>
<i className="search icon"></i>
</div>
</div>
</form>
</div>
);
}
}
export default SearchBar;
youtube-clone/src/components/style/videoitem.css
.video-item{
display:flex!important;
align-items: center!important;
cursor: pointer;
}
.video-item.item img{
max-width:180px;
}
.video-item .video-content{
overflow: hidden;
text-align: justify;
}
Edit youtube-clone/src/api/YoutubeApi.js
Get an API key from google developer google developer
import axios from "axios";
const KEY = 'API_KEY_FROM_GOOGLE_CONSOLE';
export const baseParams = {
part: "snippet",
maxResults: 5,
key: KEY
};
export default axios.create({
baseURL: "https://www.googleapis.com/youtube/v3",
});
project is live here
source code @github
ย