Build React from Scratch
MIT License
This proj is aim to implement react from 0 to 1. In the meantime the develop experience is writen down as a series of articles as follow:
You can view the release to find the corresponding code synced with the article.
There are some useful test cases from the develop experience. I've collected them as follow:
class App extends Component {
constructor(props) {
super(props)
this.state = {
count: 1
}
}
click() {
this.setState({
count: ++this.state.count
})
}
render() {
return (
<div>
<button onClick={this.click.bind(this)}>Click Me!</button>
<div>{this.state.count}</div>
</div>
)
}
}
ReactDOM.render(
<App name="count" />,
document.getElementById('root')
)
// this case is to know the attr in the jsx `<A a={1} { ...obj } />` is converted to { a: 1, b: 2, c: 3 }
class A extends Component {
render() {
return (
<div>{this.props.a + this.props.b + this.props.c}</div>
)
}
}
class B extends Component {
render() {
const obj = { b: 2, c: 3 }
return (
<div>
<A a={1} { ...obj } />
</div>
)
}
}
ReactDOM.render(
<B />,
document.getElementById('root')
)
class A extends Component {
componentWillReceiveProps(props) {
console.log('componentWillReceiveProps')
}
render() {
return (
<div>{this.props.count}</div>
)
}
}
class B extends Component {
constructor(props) {
super(props)
this.state = {
count: 1
}
}
componentWillMount() {
console.log('componentWillMount')
}
componentDidMount() {
console.log('componentDidMount')
}
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate', nextProps, nextState)
return true
}
componentWillUpdate() {
console.log('componentWillUpdate')
}
componentDidUpdate() {
console.log('componentDidUpdate')
}
click() {
this.setState({
count: ++this.state.count
})
}
render() {
console.log('render')
return (
<div>
<button onClick={this.click.bind(this)}>Click Me!</button>
<A count={this.state.count} />
</div>
)
}
}
ReactDOM.render(
<B />,
document.getElementById('root')
)
class B extends Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
this.click = this.click.bind(this)
}
click() {
for (let i = 0; i < 10; i++) {
this.setState({ // 在先前的逻辑中,没调用一次 setState 就会 render 一次
count: ++this.state.count
})
}
}
render() {
return (
<div>
<button onClick={this.click}>增加</button>
<div>{this.state.count}</div>
</div>
)
}
}
class A extends Component {
constructor() {
super()
this.state = {
count: 0
}
this.click = this.click.bind(this)
}
click() {
this.setState({
count: ++this.state.count
})
}
render() {
return <div>{this.state.count}</div>
}
}
class B extends Component {
constructor() {
super()
this.click = this.click.bind(this)
}
click() {
this.A.click()
}
render() {
return (
<div>
<button onClick={this.click}>加1</button>
<A ref={(e) => { this.A = e }} />
</div>
)
}
}
// 测试用例:验证 state 浅比较
class B extends PureComponent {
constructor(props) {
super(props)
this.state = {
count: 0
}
this.click = this.click.bind(this)
}
click() {
const state = Object.assign({}, this.state)
this.setState({
count: this.state.count + 1,
})
}
render() {
return (
<div>
<button onClick={this.click}>增加</button>
<div>{this.state.count}</div>
</div>
)
}
}
// 测试用例:验证 props 浅比较
class A extends PureComponent {
render() {
return (
<div>{this.props.count.number}</div>
)
}
}
class B extends PureComponent {
constructor(props) {
super(props)
this.state = {
count: { number: 1 }
}
}
click() {
this.setState({
count: { number: 1 }
})
}
render() {
return (
<div>
<button onClick={this.click.bind(this)}>Click Me!</button>
<A count={ this.state.count } />
</div>
)
}
}
yarn add cpreact
Especially thank simple-react for the guidance function of this library. At the meantime,respect for preact and react
If you want to contrubute this proj, you can read how to pr. Thanks!