You can find all of the code for this course here.
React is a js library that is used to produce HTML code that is shown in the browser.
The first code that we add is in index.js right under the src folder.
const App = function(){
return <div> Hey </div>;
}
The const
here (is an ES6 syntax) and tells the compiler that this is a final value of that variable.
But just creating a component is not enough. We need to add it to the DOM.
This return <div> Hey </div>;
, when converted to JS, makes a call to createElement function of React library, which takes three args.
React.createElement("tagName", "null", "insideTagContent")
.
ES6 runs on a belief of modules. So every module that we write, is independent of other modules.
The react is starting to split into two separate libraries. React core handles and works with components(Render and nest). However the functionality to render them to the DOM is in ReactDOM.
Hence the code at this stage is:
//ReduxSimpleStarter\src\index.js
import React from 'react';
import ReactDOM from 'react-dom';
const App = function(){
return <div>Get Get</div>;
}
ReactDOM.render(App);
However, the 'App' that we are trying to render here is a class and we cant render the class as it is. We need to render the instance of the class instead. we can create and instace by simply wrapping them in JSX tags like this:
const App = function(){
return <div>Get Get</div>;
}
<App></App>
Because we're in JSX, <App></App>
can be shortened to <App />
But ReactDOM.render
takes two components. The component that needs to be rendered and a target component.
var targetElement = document.querySelector('.container');
ReactDOM.render(<App />, targetElement);
const App = function(){
return <div>Get Get</div>;
}
//now becomes
const App = () => {
return <div>Get Get</div>;
}
Multi line JSX expressions are always bound inside a ():
//ReduxSimpleStarter\src\index.js
return (
<div>
<SearchBar />
</div>
)
A simple new JS file in the components folder. Eg:
//ReduxSimpleStarter\src\components\search_bar.js
import React from 'react';
const SearchBar = () => {
return <input type="text"/>
}
export default SearchBar;
//ReduxSimpleStarter\src\components\search_bar.js
import React from 'react';
class SearchBar extends React.Component {
render() {
return <input type="text"/>
}
}
export default SearchBar;
//ReduxSimpleStarter\src\components\search_bar.js
import React, {Component} from 'react';
class SearchBar extends Component {
render() {
return <input type="text"/>
}
}
export default SearchBar;
import React, {Component} from 'react';
is equal to saying import React, {Component} from 'react'; const Component = React.Component
.
It just pulls off component from react and assigns to component variable.
Every class based component should have a render() method and a return statement.
Every input Element in HTML emits a change event by default.
we can catch that like this:render() { return <input type="text" onChange = {this.onInputChange}/> }
Every event like this, defined by a browser, have an event object. Whenver we call an event handler, like a function that is called after the event is triggered. This event object is available inside that event handler.
Example:
class SearchBar extends Component {
render() {
return <input type="text" onChange = {this.onInputChange}/>
}
onInputChange(event){
console.log(event.target.value);
}
}
export default SearchBar;
State is a JS object that is used to record and react to user events. Functional components do NOT have state. Only Class based components do.
We only SET the state using this.state = {term:''}
in constructor at the time of the initialization. Apart from that, we always manipulate our state using this.setState({ term: event.target.value })
.
For example:
import React, {Component} from 'react';
class SearchBar extends Component {
constructor(props) {
super(props); //inherited from component class
this.state = {term: ''}; //initializing blank state
}
render() {
return (
<div>
<input onChange={event => this.setState({term: event.target.value})} />
Value of the input: {this.state.term}
</div>
);
}
}
export default SearchBar;
Here we use state to set the value of the input. It is suggested that we do it like this:
render() {
return (
<div>
<input
value={this.state.term}
onChange={event => this.setState({term: event.target.value})} />
</div>
);
}
This also allows us to set the value of the input beforehand.
Downward data flow means only the most parent component is responsible for the data fetching.
In ES6, the key value syntax {key : value} can be changed to {key} if key and value have the same variable names.
We can pass the data down to the child component by simply passing them as arguments to the child component - Which then arrive in the child component in 'props' and can be accessed via accessing props. For ex:
//ReduxSimpleStarter\src\index.js
//defined and set the state for the data fetched from YT.
class App extends Component{
constructor(props){
super(props);
this.state = {videos: [] };
YTSearch({key: API_KEY, term: 'surf'}, function(videos){
this.setState({videos});
});
}
}
//ReduxSimpleStarter\src\components\video_list.js
const VideoList = (props) => {
return (
<ul className="col-md-4 list-group">
{props.videos}
</ul>
);
};
var arr = [1,2,3];
arr.map(function(number) {return number * 2});
using the same map function we render a list in the template.
//ReduxSimpleStarter\src\components\video_list_item.js
const VideoListItem = (props) => {
return (
<li>VideoName</li>
);
}
export default VideoListItem;
//ReduxSimpleStarter\src\components\video_list.js
const VideoList = (props) => {
const VideoItems = props.videos.map((video) => {
return <VideoListItem key = {video.etag} video={video}/>
})
return (
<ul className="col-md-4 list-group">
{VideoItems}
</ul>
);
};
In ES6,
const VideoListItem = (props) => {
const video = props.video;
}
can be written as
const VideoListItem = ({video}) => {
};
The template strings are simply like this:
const videoURL = `www.youtube.com/embed/${videoID}`;
where videoID
is another const.
Some parent objects cannot render things fast enough to satisfy the needs of the child object.
We will be using callbacks. We start by defining a function in index.js that is passed down to the video list - which in turn passes it down to videoListItem which gives it the video that we click on and the function is executed setting the new state. for ex:
//index.js
return (
<div>
<SearchBar />
<VideoDetail video = {this.state.selectedVideo} />
<VideoList
onVideoSelect = {selectedVideo => this.setState({selectedVideo})}
videos = {this.state.videos} />
</div>
);
//video_list.js
const VideoList = (props) => {
const VideoItems = props.videos.map((video) => {
return <VideoListItem
onVideoSelect = {props.onVideoSelect}
//getting that function in video_list and passing it to VideoListItem
key = {video.etag} video={video} />
})};
//ReduxSimpleStarter\src\components\video_list_item.js
const VideoListItem = ({video, onVideoSelect}) => {
const imageURL = video.snippet.thumbnails.medium.url;
return (
<li onClick={()=>onVideoSelect(video)} className="list-group-item">
...
</li>
);}