Hi everyone, here is not getting started guide for writing React. You should have some basic of React such as basic concept of React and practical React tutorial.
I'm following Airbnb style guide and using react in pattern books for references https://github.com/krasimir/react-in-patterns, https://github.com/vasanthk/react-bits
Nowadays, we have many approaches to design the composition of react component.
Here is one of approaches to design
Preparation
create-react-app
) for reducing complexity to manage build tools such as webpack, babel, etc.Basic Design
In React documentation describes Thinking in React for explaining how to design react component and how they compose each others. However, when I 've getting started with React, I realize the component design thinking is most important thing for designing react application. In a React application, it will be at least one component, or can be divided into child component which should work with the parent one.
Advanced Design: Reusable Components
Alternative, you can use MVC approach if you familiar, however, in my opinion using MVC on react.
class Person extends React.Component {
constructor (props) {
super(props);
this.state = { smiling: false };
this.handleClick = () => {
this.setState({smiling: !this.state.smiling});
};
}
componentWillMount () {
// add event listeners (Flux Store, WebSocket, document, etc.)
}
componentDidMount () {
// React.getDOMNode()
}
componentWillUnmount () {
// remove event listeners (Flux Store, WebSocket, document, etc.)
}
get smilingMessage () {
return (this.state.smiling) ? "is smiling" : "";
}
render () {
return (
<div onClick={this.handleClick}>
{this.props.name} {this.smilingMessage}
</div>
);
}
}
Person.defaultProps = {
name: 'Guest'
};
Person.propTypes = {
name: React.PropTypes.string
};
Ref: https://github.com/chantastic/react-patterns#component-organization
function StatelessComponent(){
return (
<div>
This is Stateless Component.
</div>
)
};
function StatelessComponent({ data }){
return (
<div>
{data}
</div>
)
};
Container Component
We can split our component into 2 types: Container component, Presentational component
// CommentList.js
class CommentList extends React.Component {
render() {
return (
<ul>
{this.props.comments.map(({body, author}) => {
return <li>{body}—{author}</li>;
})}
</ul>
);
}
}
// CommentListContainer.js
class CommentListContainer extends React.Component {
getInitialState () {
return { comments: [] }
}
componentDidMount () {
$.ajax({
url: "/my-comments.json",
dataType: 'json',
success: function(comments) {
this.setState({comments: comments});
}.bind(this)
});
}
render () {
return <CommentList comments={this.state.comments} />;
}
}
Read more for Presentational and container components, using ref https://github.com/chantastic/react-patterns#container-components
if
{isActive && <p>Message</p>}
if-else
{
isTrue ? (
<span>Rendered when `TRUE`</span>
) : (
<span>Rendered when `FALSE`</span>
);
}
Loop items for JSX
const todos = [
{id: 1, text: 'Test'},
{id: 1, text: 'Write a paper'}
]
function sampleComponent(){
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
)
};
class App extends React.Component {
state = {
textbox: ""
}
render() {
return (
<div>
<input
type="text"
value={this.state.textbox}
onChange={(e) => this.setState({ textbox: e.target.value })} />
{this.state.textbox}
</div>
);
}
}
Todo Components
├── components
│ ├── todo
│ ├── index.jsx
│ ├── AddTodo.jsx
│ └── TodoList
│ ├── index.jsx
│ └── Todo.jsx
├── app.js
└── index.js
Every React component has children
props.
const Title = function () {
return <h1>Hello there!</h1>;
}
const Header = function ({ title, children }) {
return (
<header>
{ title }
{ children }
</header>
);
}
function App() {
return (
<Header title={ <Title /> }>
Resting content
</Header>
);
};
ref: https://krasimir.gitbooks.io/react-in-patterns/content/chapter-04/#passing-a-child-as-a-prop
// Counter.jsx
class Counter extends React.Component {
state = {
count: 0
}
handleAdd(){
this.setState({ count: this.state.count + 1});
}
render() {
return (
<CounterView
value={this.state.count}
onAdd={() => this.handleAdd()}>
</CounterView>
);
}
}
// CounterView.jsx
function CounterView({ value, onAdd }) {
return (
<React.Fragment>
<div>Count: {value}</div>
<button onClick={onAdd}>Add</button>
</React.Fragment>
);
};
// store.js
export default {
root: {},
getRoot() {
return this.root;
},
setRoot(value) {
this.root = value;
}
}
// Counter.jsx
class Counter extends React.Component {
constructor(props){
super(props);
this.state = {
count: 0
}
store.setRoot(this);
}
handleAdd(){
this.setState({ count: this.state.count + 1});
}
render() {
return (
<CounterView
value={this.state.count}></CounterView>
);
}
}
// CounterView.jsx
function CounterView({ value }) {
return (
<React.Fragment>
<div>Count: {value}</div>
<button onClick={() => store.getRoot().handleAdd()}>Add</button>
</React.Fragment>
);
};
Thanks for Anas
Design choice:
Read more how to implement in each state management library in React State Museum
Read more in Airbnb's Style guide
class Owner extends React.Component {
handleClick () {
// handle click event
}
render () {
return <div onClick={() => this.handleClick()}></div>;
}
}
Original: https://github.com/chantastic/react-patterns#naming-events
Other topics can read in below resources:
State
P.S. PR, Suggestions are welcome