Custom Functions in React
Event Handler Naming Conventions
React uses camelCase for event names. The HTML onclick becomes onClick, and onchange becomes onChange.
Basic Click Events
When attaching event handlers, avoid parentheses—adding () immediately invokes the function:
import React, { Component } from 'react';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {};
}
handleClick() {
console.log('Button clicked');
}
render() {
return (
<div>
<button onClick={this.handleClick}>Click Me</button>
</div>
);
}
}
Accessing the Event Object
Custom event handlers receive the event object as a default parameter:
import React, { Component } from 'react';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {};
}
handleClick(event) {
console.log('Button clicked', event);
}
render() {
return (
<div>
<button onClick={this.handleClick}>Click Me</button>
</div>
);
}
}
Handling this Context in Event Handlers
The this keyword is undefined inside custom methods. Bind this in the constructor:
import React, { Component } from 'react';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('Button clicked', this);
}
render() {
return (
<div>
<button onClick={this.handleClick}>Click Me</button>
</div>
);
}
}
Inline Binding (Alternative Approach)
Bind this directly in the render method:
import React, { Component } from 'react';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {};
}
handleClick() {
console.log('Button clicked', this);
}
render() {
return (
<div>
<button onClick={this.handleClick.bind(this)}>Click Me</button>
</div>
);
}
}
Passing Arguments to Event Handlers
Use .bind() to pass custom arguments alongside the event object:
import React, { Component } from 'react';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {};
}
handleClick(message) {
console.log('Button clicked', this);
console.log(message);
}
render() {
return (
<div>
<button onClick={this.handleClick.bind(this, 'Custom message')}>
Click Me
</button>
</div>
);
}
}
Component Lifecycle Methods
Comparison with Vue
| Vue Lifecycle | React Lifecycle |
|---|---|
| created | constructor |
| mounted | componentDidMount |
| updated | componentDidUpdate |
| beforeDestroy | componentWillUnmount |
Legacy Lifecycle Hooks (Deprecated in React 16.3+)
Initialization Phase
constructor(props)— Initialize state and bind methodscomponentWillMount()— Legacy method, deprecatedrender()— Required method for rendering UIcomponentDidMount()— Fetch data, manipulate DOM, equivalent to Vue'smounted
Update Phase
componentWillReceiveProps(nextProps)— Legacy method, deprecatedshouldComponentUpdate(nextProps, nextState)— Returns boolean, crucial for performance optimizationcomponentWillUpdate()— Legacy method, deprecatedrender()— Re-renders the viewcomponentDidUpdate()— DOM operations, avoid data fetching here
Destruction Phase
componentWillUnmount()— Cleanup before component removal, similar to Vue'sbeforeDestroy
Modern Lifecycle Methods (React 16.3+)
Initialization Phase
constructor(props)static getDerivedStateFromProps(props, state)— Returns state object or null, called before renderrender()componentDidMount()
Update Phase
static getDerivedStateFromProps(props, state)shouldComponentUpdate(nextProps, nextState)render()getSnapshotBeforeUpdate(prevProps, prevState)— Capture values before DOM updatescomponentDidUpdate(prevProps, prevState, snapshot)
Destruction Phase
componentWillUnmount()
Error Handling
static getDerivedStateFromError(error)componentDidCatch(error, info)
State Management with setState()
import React, { Component } from 'react';
import axios from 'axios';
export default class ProductList extends Component {
constructor(props) {
super(props);
this.state = {
products: []
};
}
componentDidMount() {
axios.get('/api/products').then(response => {
this.setState({
products: response.data.results
});
});
}
render() {
const { products } = this.state;
return (
<div>
{products.map(item => (
<div key={item.id}>
<h3>{item.name}</h3>
<span>${item.price}</span>
</div>
))}
</div>
);
}
}
Environment-Based Webpack Configuration
Install the cross-env package:
npm install cross-env --save-dev
package.json scripts:
"scripts": {
"start": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js",
"build": "cross-env NODE_ENV=production webpack --config webpack.config.js"
}
webpack.config.js plugins:
const isDev = process.env.NODE_ENV === 'development';
module.exports = {
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: isDev ? '"development"' : '"production"'
}
}),
new HtmlWebPackPlugin({
template: './src/index.html'
})
]
};
API Request Abstraction
utils/httpClient.js
import axios from 'axios';
const isDev = process.env.NODE_ENV === 'development';
const httpClient = axios.create({
baseURL: isDev ? '/api' : 'http://production-server.com'
});
httpClient.interceptors.request.use(config => {
config.headers['Authorization'] = localStorage.getItem('authToken');
return config;
});
httpClient.interceptors.response.use(response => {
return response.data;
});
export default httpClient;
utils/endpoints.js
import httpClient from './httpClient';
const fetchProducts = (page = 0, limit = 10) => {
return httpClient.get('/products', {
params: { page, limit }
});
};
const fetchSlides = (type = 'home') => {
return httpClient.get('/slides', {
params: { category: type }
});
};
export { fetchProducts, fetchSlides };
Component Composition
ParentComponent.jsx
import React, { Component } from 'react';
import { fetchSlides, fetchProducts } from './utils/endpoints';
import ProductGrid from './ProductGrid';
export default class ParentComponent extends Component {
constructor(props) {
super(props);
this.state = {
slides: [],
products: []
};
}
componentDidMount() {
fetchSlides().then(data => {
this.setState({ slides: data.results });
});
fetchProducts().then(data => {
this.setState({ products: data.results });
});
}
render() {
return (
<div>
<div className="carousel">
{this.state.slides.map(item => (
<img key={item.id} src={item.imageUrl} alt="" />
))}
</div>
<ProductGrid items={this.state.products} />
</div>
);
}
}
ProductGrid.jsx
import React, { Component } from 'react';
export default class ProductGrid extends Component {
render() {
return (
<div className="product-list">
<div className="product-item">
<img src="" alt="" style={{ width: '80px' }} />
<h4>Sample Product</h4>
<p>$299.99</p>
</div>
</div>
);
}
}
Passing Props from Parent to Child
Parent components pass data to children via custom attributes. Variables, booleans, and numbers require curly braces:
<ProductGrid items={this.state.products} />
Child components access props through this.props:
import React, { Component } from 'react';
export default class ProductGrid extends Component {
render() {
return (
<div>
{this.props.items.map(product => (
<div key={product.id}>
<img src={product.thumbnail} style={{ width: '80px' }} />
<h4>{product.name}</h4>
<p>${product.price}</p>
</div>
))}
</div>
);
}
}
Prop Type Validation
Install prop-types package:
npm install prop-types --save
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class ProductGrid extends Component {
render() {
return (
<div>
{this.props.items.map(product => (
<div key={product.id}>
<img src={product.thumbnail} style={{ width: '80px' }} />
<h4>{product.name}</h4>
<p>${product.price}</p>
</div>
))}
</div>
);
}
}
ProductGrid.propTypes = {
items: PropTypes.array
};
Available type validators: bool, array, func, number, object, string, symbol, node, element.
Passing Data from Child to Parent
Children communicate with parents by receiving callback functions as props.
ChildComponent.jsx
import React, { Component } from 'react';
export default class ChildComponent extends Component {
render() {
return (
<div>
<button onClick={() => this.props.onSend('Data from child')}>
Send to Parent
</button>
</div>
);
}
}
ParentComponent.jsx
import React, { Component } from 'react';
import ChildComponent from './ChildComponent';
export default class ParentComponent extends Component {
handleChildData(payload) {
console.log('Received from child:', payload);
}
render() {
return (
<div>
<ChildComponent onSend={this.handleChildData.bind(this)} />
</div>
);
}
}
React Project Scaffolding Options
Option 1: Create React App (Recommended)
npx create-react-app my-project
Option 2: Manual Setup
npm install -g create-react-app
create-react-app my-project
Option 3: Dva Framework
npm install -g dva-cli
dva new my-project