In this session we will learn
- Router
- Link & Nav Link
- Higher Order Components(HOC)
- Programatic Redirects
- Axios (Nodejs utility for AJAX)
- Route Parameters
- Switch Tag to link only exact match
- Importing Images
- Redux Intro
- Integrating with Jquery
Installations Required
For Create React App and React basic stuff
npx create-react-app my-app
For extra utilities in this chapter
npm install react-router-dom
npm install axios
npm install redux react-redux
React Router
To use React router, you must install react-router package
npm install react-router-dom
Sample app creates an SPA poketimes
with Home, About Us & Contact Page
Steps:
- Create a new folder
components
in src folder - Create components for each page there. Home.js, About.js, Contact.js & Navbar.js
- import router classes. see App.js & Navbar.js
import { Route, BrowserRouter } from 'react-router-dom'
- Enclose entire App JSX in
<BrowserRouter>
tag; - Use
<Route>
tag to switch to component eg:<Route path='/about' component={About} />
. - For home page use
exact
keyword to avoid home conetents in other pages on top. eg:<Route exact path='/' component={Home}/>
Links & Navlinks
Stop requests to Server
In Navbar.js
- import Link, NavLink
import { Link, NavLink } from 'react-router-dom'
- Change
<a href=
to<Link to=
. (PS: 'Link' was imported) - if we use
<NavLink to=
instead of<Link to=
, an additional classactive
will be added toa tag
when clicked
27. Programatic Redirects
When enclosed in <Route>
tag, some additional info is send to props
, history, location, match(is exact etc), content.
We can use props.history.push('/newURL'); to redirect programatically. eg: props.history.push('/about');
In the case of Navbar, which is not enclosed in <Route>
tag, we need to use Higher order component WithRouter
. It gives extra properties to props.
It has to be imported first
import { Link, NavLink, withRouter } from 'react-router-dom'
And then used to wrap in export
export default withRouter(Navbar)
28. More about Higher order components
Higher Order Components are function that wraps components to supercharge them with extra properties and methods
eg: hoc/Rainbow.js
import React from 'react'
const Rainbow = (WrappedComponent) => {
const colours = ['red', 'pink', 'orange', 'blue', 'green', 'yellow'];
const randomColour = colours[Math.floor(Math.random() * 6)];
const className = randomColour + '-text';
return (props) => (
<div className={className}>
<WrappedComponent {...props} />
</div>
)
}
export default Rainbow
which is used in components/About.js
import Rainbow from '../hoc/Rainbow'
and
export default Rainbow(About)
29. Using Axios
Axios is a Javascript library used to make HTTP requests from node. js or XMLHttpRequests from the browser and it supports the Promise API that is native to JS ES6. It can be used intercept HTTP requests and responses and enables client-side protection against XSRF. It also has the ability to cancel requests. It is isomorphic (= it can run in the browser and nodejs with the same codebase).
On the server-side it uses the native node.js http module, while on the client (browser) it uses XMLHttpRequests.
PS: Instead of Axios, fetch
could be used, but this chapter is giving an intro to axios in nodejs.
eg:
fetch('https://jsonplaceholder.typicode.com/posts/')
.then(response => response.json())
.then(json => console.log(json))
is same as
axios.get('https://jsonplaceholder.typicode.com/posts/')
.then(res => {
console.log(res.data);
})
To test with react it should be installed with npm
npm install axios
In this test REST API from Free fake API for testing and prototyping. is used.
- Import axios
import axios from 'axios'
. - Use the lifecycle method
componentDidMount
to fetch data on page load in components/Home.js
componentDidMount(){
axios.get('https://jsonplaceholder.typicode.com/posts/')
.then(res => {
console.log(res);
this.setState({
posts: res.data.slice(0,10)
});
})
}
this.setState will force render() , see life cycle
and in in render. Usefull CSS classes from materialize card, card-content,cart-title
.
<div className="post card" key={post.id}>
<div className="card-content">
<span className="card-title">{post.title}</span>
<p>{post.body}</p>
</div>
</div>
30. Route Parameters
Extracting variables in url. This is similar to .htaccess
-
in App.js ,
use<Route path='/:post_id' component={Post} />
.Post component is to be created. -
Use in
<Link to={'/' + post.id} />
in Home.js -
Create a new Component Post.js
get post id as follows
componentDidMount(){
let id = this.props.match.params.post_id;
this.setState({
id
})
}
32. Switch Tag to link only exact match
As in .htaccess, /:post_id
and /contact
may be treated similarly. to avoid this there are two options
- create unique prefix for dynamic urls eg
/posts/:post_id
in<Route/>
in in App.js and use<Link to={'/posts/' + post.id} />
in Home.js
OR
- use
<Switch />
tag from react-router-dom (must be imposted first) inside<Navbar>
tag in Home.js.
This ensure that only one of the links in the list of links in<Navbar>
will be taken and rest discarded.
33. Importing Images
- Image to be imported must be saved in
/src
folder import Pokeball from '../pokeball.png'
in Home.js- use as
<img src={Pokeball} alt="A Pokeball" />
- some changes are made in index.css for this chapter
34. Redux Intro
Redux
- Central data store for all app data
- Any component can access data from it
- Makes state management easy
Process
- there is a central store which represents the
global state of the application
. - there is a
Reducer
class - Component classes dispatch action , reducer captures it.
- Reducer updates central store
- props of other components subscribed to it will get updated.
35. Redux Stores
Test with Codepen
Net ninja URL for this chapter is https://codepen.io/MickGe/pen/VweoQJj
- Go to JS settings
- Set JS Preprocessor as
Babel
- Set cdnjs url of redux in the tuorial https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.0-rc.1/redux.js Latest we get by searching in the window is 4.2.1
- url of codepen redux project is https://codepen.io/osolsolutions/pen/gOjyeMp
- change project title as
Redux Basics
. - click
console
button at bottom left
Edit JS
Important points
- extract createStore from Redux.
const { createStore } = Redux;
' - create a reducer.myreducer is just a function that interacts with the store. it takes 2 parameters ,
state
andaction
. action will have a type property. eg:{ type: "ADD_TODO", todo: "buy milk" }
.
function myreducer(state = initState, action) {
Change in state will be made in reducer depending on type
of action.
eg:
if (action.type == 'ADD_TODO') {
return {
...state,
todos: [...state.todos, action.todo]
}
}
This is similar to setState
in Component classes. But unlike setState in components, where only required properties is to be set, in reducer all properties must be set
. that is why ...state,
is prepended.
- Create an initial state
initState
to pass to reducer on page load.const initState = { todos: [], posts: [] };
- create store with redcer as arfgument `const store = createStore(myreducer);
- store.dispatch(action)
- store.subscribe(, we will get the current state with
store.getState()
.
36. Redux Actions
37. Redux Cont'd
38. Redux Cont'd Part 3
Final code is
const { createStore } = Redux;
const initState = {
todos: [],
posts: []
};
function myreducer(state = initState, action) {
if (action.type == 'ADD_TODO') {
return {
...state,
todos: [...state.todos, action.todo]
}
}
if (action.type == 'ADD_POST') {
return {
...state,
posts: [...state.posts, action.post]
}
}
};
const store = createStore(myreducer);
store.subscribe(() => {
console.log('state updated');
console.log(store.getState());
})
store.dispatch({ type: "ADD_TODO", todo: "buy milk" });
store.dispatch({ type: "ADD_TODO", todo: "sleep some more" });
store.dispatch({ type: "ADD_POST", post: "egg hunt with Yoshi" });
39. Redux Part4 (Using Redux in React)
To use in create react app, 2 modules must be installed
- redux
- react redux(serves as a layer between react and redux)
npm install redux react-redux
Steps to use redux in react
- Redux related objects must me imported in index.js
import { createStore } from 'redux'
import { Provider } from 'react-redux'
- Provider should wrapp
<App />
.
ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('root'));
-
create reducer rootReducer to pass to
const store = createStore(rootReducer);
-
import rootReducerin index.js
40. Using component to interact with redux
Component Used is [Home.js](rootReducer
import { connect } from 'react-redux'
In export wrap it in a method that maps the state to props
, here state.posts to props.props
. state will be available when it is embedded in react-redux.connect()
. ie a higher order component is created with connect(mapStateToProps)
, which is then used to wrap Home , so as to give it an extra power, here give props from state.
The first parameter to
connect
is similar tostore.subscribe(
in a non class js ,as in this . it gets central state as argument, where as to get state in store.subscribe, you shoulduse store.getState()
const mapStateToProps = (state) => {
return {
posts: state.posts
}
}
export default connect(mapStateToProps)(Home)
41. Blog Detail Page
Filter from state, the required item send via props
const mapStateToProps = (state, ownProps/*props received via tag*/) => {
let id = ownProps.match.params.post_id;
return {
post: state.posts.find(post => post.id === id)
}
}
export default connect(mapStateToProps)(Post)
42. Map Dispatch to Props
Interact with state in central store. eg: Delete, dispatch event, which is caught by reducer and central state is changed accordingly.
{Video](https://www.youtube.com/watch?v=40pWMVMnftc&list=PL4cUxeGkcC9ij8CfkAY2RAGb-tmkNwQHG&index=42)
Git
const mapDispatchToProps = (dispatch) => {
return {
deletePost: (id) => dispatch({type: 'DELETE_POST', id: id})
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Post)
The second parameter to
connect
receivestore.dispatch
as its argument
In render
<div className="center">
<button className="btn grey" onClick={this.handleClick}>
Delete Post
</button>
</div>
and add the method handleClick
handleClick = () => {
this.props.deletePost(this.props.post.id);
this.props.history.push('/');
}
anin in rootReducer
const rootReducer = (state = initState, action) => {
console.log(action);
if(action.type === 'DELETE_POST'){
let newPosts = state.posts.filter(post => {
return post.id !== action.id
});
return {
...state,
posts: newPosts
}
}
return state;
}
43 Action Creaters
Action creators are used to seperate code , so as to make exclusive class/function that handles dispatch
event. so the code is more organised.
Action creater used in this project is actions/postActions.js
export const deletePost = (id) => {
return {
type: 'DELETE_POST',
id
}
}
and in
import { deletePost } from '../actions/postActions'
and
const mapDispatchToProps = (dispatch) => {
return {
deletePost: (id) => dispatch(deletePost(id))
}
}
44. Wrapup and next steps
New Play list of React, Redux and Firebase App , 40 videos
|
|