-
Notifications
You must be signed in to change notification settings - Fork 0
React
- Install Babel CLI globally - npm install -g babel-cli
- Install Babel presets to prj folder - npm install babel-preset-react@6.24.1 babel-preset-env@1.5.2
- Command to run babel to compile and copy to public folder -> Babel src/app.js --out-file=public/scripts/app.js --presets=env,react --watch
- To run the app use Live-server as the webserver. Navigate to the app folder and enter command live-server ex, live-server public
- JSX stands for JS Xml - Extension of JS
- Variables and objects can be referred inside {} within html tags which in turn is defined as a template variable and rendered using ReactDOM.
var template = (
<div>
<h1>{app.title}</h1>
<p>{app.subtitle}</p>
</div>
);
var appRoot = document.getElementById('root');
ReactDOM.render(template,appRoot);- Conditional rendering: Directly reference function in the template and conditionalize within the function. Ex:
<div>
<p>{app.subtitle}</p>
{getLocation(user.location)} -> Function will return a <p> tag based in the presence of location.
</div>- Undefined/null/boolean are ignored by JSX and not rendered.
- Alternate for conditional rendering - Ternary and logical AND operators. Logical AND: age > 18 &&
Adult
-> With this we specify only true condition. - Const, let, var are all function scoped. Meaning it cannot be referenced outside the function where it was defined. Const & let are also block scoped unlike var.
- Arrow Functions - Don't have a function name, so need to be always assigned to a const/var. ex: const square = (x) => { return xx; }; Concise version: const square = (x) => xx;
- 'this' when used in an arrow function looks for objects from its parent function. So parent function cannot be arrow if using 'this', should use es5 function instead.
- Foreach & map are functions that loop thru an array. Ex: this.cities.forEach. Difference is Map transforms the output of an array.
- Es6 function syntax within objects— multiply() { code }; In es5 this was written as multiply: function () { code };. Refer code file for more details on function and map.
- Forms:-
- Function to be called for Button onSubmit event should just be referenced by name and shouldn’t have the (). For ex, Add
- The function will get called with the event object as the input argument that can be referenced. For ex; Const onFormSubmit = (e) => {}
- Event e has a method called preventDefault() that prevents the whole page from refreshing and instead use client side JS.
- e.target is the element on which the action started on. Ex, e.target.elements..value
- Arrays in JSX:-
- Can be directly used in JSX. Ex;
{ [1,2,3] }or{ [<p>a</p>, <p>b</p>, <p>c</p>] } - When using html tags we need to use a unique key so that React can identify it uniquely. So earlier ex should be
{ [<p key="1">a</p>, <p key="2">b</p>, <p key="3">c</p>] }
- Can be directly used in JSX. Ex;
- Classes: Refer classes-1.js
- Similar to JS classes. Create new instances as const me = new Person();
- Constructor method is the method that executes when class is instantiated. We can also set up defaults as constructor(name = 'Anonymous') { …}
- Other methods of the class are accessed after instantiation using dot operator. Ex; me.getGreeting()
- Template strings - Uses ` (ticks) instead of ". Advantage - directly refer vars or expressions. Ex;
Hi ${this.name}!! - Extends - to inherit from another class.
- Super() - Function to call the parent method. Ex;-
class Student extends Person {
constructor(name, age, major) {
super(name, age); --> calls the parent constructor method
this.major = major;
}
} - Another way of accessing parent method is: let description = super.getDescription();
- Components:
- Create React components as classes. Class's first letter should be upper case.
- These classes will need to extend from React.Component and have a render() function within it which will return the actual JSX to be rendered.
- The components/classes can then be referred as an html tag. Ex;
- Props - value passed to React components. Props are passed as key/value pairs like an object. Ex; <Header title={"test header"} />; then inside the Header component we can access it as this.props.title.
- However props may not be bound to other functions within the same component. For ex; onclick event functions may not have access to this.props… In order to fix this we need to use the bind method in the constructor function of the class. Ex:
constructor(props) {
super(props);
this.handleRemoveAll = this.handleRemoveAll.bind(this);
}- Doing the bind in the constructor ensures that 'this.props' is available throughout the class. The bind method returns a new method with
thisreferring to the first argument passed. - Component State:
- Is an object within the component - Key/value pair
- Component initially renders with the default state and if it changes React automatically re-renders.
- We initially define state as an object - Ex; this.state = { count: 0 }
- Then to update the state we need to use setState function. prevState object holds the previous state and this should always be used to refer state since the setState calls are async. Ex:
this.setState((prevState) => {
return { count: prevState.count + 1};
})- Manipulating the state variables should happen in the parent component. So we need to define functions that alter state in parent. But in order to call this from a child, define the function and then pass it as a prop to child and then reference from there. Ex;
handleRemoveAll() {
this.setState(() => {
return { options : []}
});
}<Action optLen={this.state.options.length} handlePick={this.handlePick}/> -> then in the child class reference as onClick={this.props.handlePick}
- Stateless components:
- Doesn’t have or use states but allows use of props.
- It is defined simply like what the render function does in a state Component .
- For props, access is through prop parm that is passed to it but it doesn’t have access to 'this'. So just refer directly. Ex
const User = (prop) => {
return (
<div>
<p>Name: {prop.name}</p>
</div>
);
}###IMP: When we don’t need to use state, we can use stateless components which is just like a simple arrow function that takes props as the input returns some JSX(but its name should be like a class i.e. start with caps). Stateless component also do not need to extend React.Component, doesn’t need a render method, this binding or constructor fn. Refer React hooks section below
-
Filter method - The filter() method creates a new array with all elements that pass the test implemented by the provided function.
-
LifeCycle method -
- componentDidMount () - Method fires when class based components render. Wont fire for stateless components
- componentDidUpdate() - 2 arguments - prevProps & prevState.
- componentWillUnmount() - Fires when a component goes away.
-
Local Storage:
- localStorage.setItem - to store items as key/value pairs. Ex; localStorage.setItem('name','Aruun')
- .removeItem, localStorage.getItem
- To store objects we need to use stringify. i.e. convert to JSON Ex; JSON.stringify({age:25})
- To convert back to object - JSON.parse()
-
Exports & imports - For breaking components into diff files
- Named export - Export assigns the same name as the const/function and import needs to reference the same name. ex; export const square (x) => x*x or define the function and then export {square}…. Then import {square} from './util.js'
-
Default export - no name is assigned and can be accessed via import with anyname. But export default cannot be used inline with the function but instead should be defined separately as export default square. However for class definition export can be used inline.
-
Only 1 default export per component.
-
Class properties - Babel plugin that allows us to do away with constructor functions and explicit 'this' binding.
- Install the babel plugin (transform-class-properties) and reference it via .babelrc file.
- Then we can remove constructor functions in the class and instead define them directly. Ex; state = { error: undefined };
-
Similarly instead of explicit 'this' binding for functions we just need to convert them to arrow functions.
-
3r party Components:
- For components, instead of passing dynamic content via props we can also pass them inline. Ex:
ReactDOM.render(<IndecisionApp><p>This is inline content </p></IndecisionApp>, document.getElementById('app');
- For components, instead of passing dynamic content via props we can also pass them inline. Ex:
-
Then access them inside the component using props.children reference.
-
Styles:
- We need to tell webpack to load styles from a CSS. This is better than referring CSS file directly in HTML.
- First add a rule to webpack config file to look for CSS file and to run the loader package.
- Install style-loader, css-loader, sass-loader & node-sass packages from npm. The last 2 are for SCSS (advanced CSS).
- Then import the styles into app.js via import statement.
-
React Router:
- Router is basically client side rendering/routing wherein trip to servers are avoided when possible. Basically based on the URL path we can make react render pages from components directly.
- Install react-router-dom and then import BrowserRouter and Route.
- To tell the browser/react that it should look for routes instead of going to server for different url paths we need to update webpack config and the parm- historyApiFallback: true. i.e. make 404 fallback to index.html
-
We then use
<BrowserRouter>component once and then for every routing we use one instance of<Route>component. Ex:
<BrowserRouter>
<div>
<Route path="/" component={ExpenseDashboardPage} exact={true}/>
<Route path="/create" component={AddExpensePage} exact={true}/>
</div>
</BrowserRouter>- Use Exact={true} option to ensure BrowserRouter matches the exact path. Else it will make the "/" true event if the path is "/create".
- Switch component is similar to switch/evaluate stmt. Import Switch component and then replace the
<div>above with<switch>. Now react will evaluate every route statement and stop at the first match. We can use this for default page not found handling. - To redirect to other pages from one page, we can setup the routing using
LinkOrNavLinkcomponents instead of using<a>tag. This will ensure request doesn’t go to the server. Ex:<Link to="/create">Create Expense</Link> - NavLink is an advanced version of Link. For instance to format or highlight the selected link use NavLink. Exact option is similar to above in Route.
Ex:
<NavLink to="/" activeClassName="is-active" exact={true}>Home </NavLink> - To render other components we can simply use them within the BrowserRouter component.
- Best practice is to break down router code into its own router component.
- When components are called from Route, react router passes a set of system props that contain the query string, specific resource IDs or # values for in page navigation.
- URL resources can be accessed by setting the router like
<Route path="/edit/:id" component={EditExpensePage} /> - Then the variable can be accessed as key value pairs from the match.params prop.
-
React state is stored locally within a component. When it needs to be shared with other components, it is passed down through props. In practice, this means that the top-most component in your app needing access to a mutable value will hold that value in its state. If it can be mutated by subcomponents, you must pass a callback to handle the change into subcomponents. When using Redux, state is stored globally in the Redux store. Any component that needs access to a value may subscribe to the store and gain access to that value.
-
Is a state container used for maintaining states. This solve some of the drawbacks of the component states that we used previously. Some of those drawbacks are
- need to pass props multiple levels down and so components are not truly reusable as they are tightly tied to their immediate parent
- If we have 2 components that do not share a parent then we cannot share state between those components
- If a child component 2 levels below needs a state value, the immediate parent needs to pass the state function/state as a prop to the child though the component itself doesn’t need it
-
After redux is installed we need to import it and then call createStore function. getState is used to fetch the state/store.
-
createStore takes a callback function where we define the what needs to be set as state. In below ex, we set state object with a variable count as 0. Ex:
import {createStore} from 'redux'
const store = createStore((state = {count:0}) => {
return state;
});
console.log(store.getState());- Actions - used to change/update the state of the store. An action is a plain JavaScript object that has a type field. You can think of an action as an event that describes something that happened in the application.
- Dispatch - to send actions to the store. Ex:
store.dispatch({
type: 'INCREMENT'
})- Then in the store above it is available as the 2nd argument and we then need to handle increment action.
const store = createStore((state = {count:0}, action) => {
switch (action.type) {
case 'INCREMENT':
return {
count : state.count + 1
};
default:
return state;
}
});- Store.subscribe - gets called every time the state is changed. This takes a callback function.
store.subscribe(() => {
console.log("state changed");
})-
To unsubscribe we assign the
store.subscribeto a const and then call it as a function. Ex:const unsubscribe = store.subscribe…. (As above)… Thenunsubscribe()—> this will stop subscription -
Similar to type we can also pass other user defined objects in store.Dispatch. Ex: store.dispatch({ type: 'INCREMENT' , incrementBy: 5 }). Then refer this as action.incrementBy
-
Reducers -
- A reducer is a function that receives the current state and an action object, decides how to update the state if necessary, and returns the new state: (state, action) => newState. You can think of a reducer as an event listener which handles events based on the received action (event) type.
- Reducers are pure functions. i.e. return depends on all the input arguments.
- They never change the state or action
- The callback function in the createStore example above is a reducer function. Ex: const store = createStore(expenseReducer); -> expenseReducer refers to the reducer fn.
- combineReducers is a redux component that lets handling of multiple reducers. For instance if there are multiple objects for which we need to manage the state then typically we will have a reducer function for each object. In order to pass multiple reducer functions to createStore request, we need to use combineReducers which takes an obj as i/p. Ex:
const store = createStore(
combineReducers({
expenses: expenseReducer, // expenses is the obj being passed to the store and expenseReducer is the reducer fn for this obj.
filter: filterReducer
})
);- Basically the redux store operations can be broken out into different components; Refer Trainings/React/Expensify-App/src/playground-course-ver/redux-101.js
- The Action which does a
Dispatchof an action and this can be in its own function(say action gen fn). Ex:store.dispatch(addExpense({ description: 'car', amount: '450'})); - The action generator function sets the action parms like type & other user defined obj props. Ex -
- The Action which does a
const RemoveExpense = ({id} = {} ) => ({
type: 'REMOVE_EXPENSE',
expense: {
id
}
})- The reducer function is the fn called by createStore either directly or using combineReducers.
- The reducer fn then has logic to handle the different dispatch actions as well as default when the store is initially created. Ex-
const expenseReducer = (state = expenseReducerDefaultState, action) => {
switch(action.type) {
case ('ADD_EXPENSE'):
return [
...state, //... is called spread operator and is used to append items to array
action.expense]
case ('REMOVE_EXPENSE'):
return state.filter((exp) => (exp.id !== action.expense.id));
default:
return state;
}
};-
React with Redux:
- HOC - Higher Order components. Basically provides wrapping capability. For ex; to add conditional features like displaying privileged info for certain components.
- Any actions/dispatch on a store will automatically re-render components which makes it 'Reactive'
- Install react-redux library. Use Provider component from this lib that lets us share the store across diff components. Ex;
<Provider store={store}>
<AppRouter />
</Provider>- Then use the connect lib to access the store from other components. Ex;
export default connect(mapStateToProps)(ExpenseList)
const mapStateToProps = () => { //This function is the callback fn to connect and gets the state info and passed as props to the component ExpenseList
return {
expenses: state.expenses
}
};
const ExpenseList = (props) => (
<div>
{props.expenses.length}
</div>
);-
With React Redux, your components never access the store directly -connect does it for you. React Redux gives you two ways to let components dispatch actions:
- By default, a connected component receives
props.dispatchand can dispatch actions itself. -
connectcan accept an argument calledmapDispatchToProps, which lets you create functions that dispatch when called, and pass those functions as props to your component.
- By default, a connected component receives
-
If you don't specify the second argument to
connect(), your component will receive dispatch by default. Ex: connect( null, null) (MyComponent) -
Providing a
mapDispatchToPropsallows you to specify which actions your component might need to dispatch. It lets you provide action dispatching functions as props. Therefore, instead of callingprops.dispatch(() => increment()), you may callprops.increment()directly. -
Changing lists dynamically - Setup an input text field and set an onChange event which will do a dispatch to the store. This inturn will rerender the app as the store value changes. EX:
const ExpenseListFilter = (props) => (
<div>
<input type="text" value={props.filters.text} onChange={ (e) => { ///every keystroke will trigger onchange
props.dispatch(setTextFilter(e.target.value));
//every time it will send dispatch action to store with setTextFilter which will set the filter to what is in this field.
// As the store changes the screen will re-render
}}
</div>
)- Moment.js - time/date library
Server Side Rendering
- Prerendering html pages on server so that the first rendering on the client isn’t very slow
- This also helps in SEO (Search engine optimization) as without SSR, Search engine crawlers can’t see a rendered page
- This applies only to the first call for SPAs and subsequent requests are handled on the client itself.
- The latest release of react introduces Hooks that let us manage state easily without using stateful class components and the recommendation is to use this as much as possible
- Hooks allow you to reuse stateful logic without changing your component hierarchy. It lets you split one component into smaller functions based on what pieces are related (such as setting up a subscription or fetching data)
- Hooks are functions that let you “hook into” React state and lifecycle features from function components. React provides a few built in hooks like useState, useEffect.
useState
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0); // Initial value of state is 0
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}-
useStatereturns a pair: the current state value and a function that lets you update it. Ex; setCount provides/updates the value of the state var count. - Unlike
this.state, it doesn’t have to be an object and can be string, int, obj, etc. - In function components, the execution of the whole function is the equivalent of the render function in class components.
Effect Hook / useEffect
- The Effect Hook adds the ability to perform side effects (data fetching, changing DOM etc) from a function component and serves the same purpose as componentDidMount, componentWillUnmount etc., in React classes, but unified into a single API.
- As with lifecycle method we would use it when we want a certain action to take place each time a component is updated or loads the first time.
- If we want the same action to take place after first mount and every update, with lifecycle methods we will have to call the same code in multiple methods. useEffect simplifies that as this can now be defined within a single function,
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});- By default, React runs the effects after every render — including the first render.
- Just like with useState, you can use more than a single effect in a component.
- Effects may also optionally specify how to “clean up” after them by returning a function. Ex:
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});- We can use multiple useEffects for different effects that need to be grouped together
Rules of Hooks
- Only call Hooks at the top level. Don’t call Hooks inside loops, conditions, or nested functions.
- Only call Hooks from React function components. Don’t call Hooks from regular JavaScript functions.
- Reuse of Stateful logic between components was earlier possible only through customization like higher-order components and render props. With custom hooks we can do this easily without adding more components to the tree. Refer this example