React Learning Record

Start

1
2
npm i -g create-react-app@1.5.2
create-react-app react-app

Inside that directory, you can run several commands:

1
2
3
4
5
6
7
8
9
10
11
12
yarn start
Starts the development server.

yarn build
Bundles the app into static files for production.

yarn test
Starts the test runner.

yarn eject
Removes this tool and copies build dependencies, configuration files
and scripts into the app directory. If you do this, you can’t go back!

Bootstrap

1
npm i -s bootstrap@4.1.1

index.js

1
import 'bootstrap/dist/css/bootstrap.css';

export

Add Component/counter.jsx to src

1
2
3
4
export default class Counter extends Component {

render() {}
}

equals:

1
2
3
4
5
class Counter extends Component {

render() { }
}
export default Counter;

ReactDOM.render

In index.js, it render th App.js

1
2
3
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

can be repalced by this to render Counter.js :

1
2
3
import Counter from './components/counter';

ReactDOM.render(<Counter />, document.getElementById('root'));

Use component

In App.js,add:

1
2
3
4
5
6
return (
<div className="App">
...
<Counter />
</div>
);

React.Fragment

If use

, there is a useless element

If delete


Use <React.Fragment> instead:

State

1
2
3
4
5
6
7
8
9
10
11
12
13

export default class Counter extends Component {
state = {
count: 0
};
render() {
return (
<React.Fragment>
<span>{this.state.count}</span>
</React.Fragment>
);
}
}

Function return and expression

1
2
3
4
5
6
7
8
9
10
11
12
13
14
state = {
count: 0
};
render() {
return (
<React.Fragment>
<div>{this.formatCount()}</div>
</React.Fragment>
);
}

formatCount() {
return this.state.count === 0 ? 'Zero' : this.state.count;
}

Eauqls to :

1
2
3
4
formatCount() {
const { count } = this.state;
return count === 0 ? 'Zero' : count;
}

We can also insert elements and variable:

1
2
3
4
5
formatCount() {
const { count } = this.state;
const x = <h1>Zero</h1>
return count === 0 ? x : count;
}

Image src

1
2
3
4
5
6
7
8
9
10
state = {
imageUrl: 'https://picsum.photos/200'
};
render() {
return (
<React.Fragment>
<img src={this.state.imageUrl} alt="" />
</React.Fragment>
);
}

Use Bootstrap CSS

Be sure to use className, not class

1
2
<div className="badge badge-primary m-2">{this.formatCount()}</div>
<button className="btn btn-secondary btn-sm">Increcement</button>

Inline CSS

1
<div style={{ fontSize: 30 }} className="badge badge-primary m-2">Zero</div>

Or:

1
2
3
4
5
6
7
8
aaa = { fontSize: 30 };
render() {
return (
<React.Fragment>
<div style={ this.aaa } className="badge badge-primary m-2">Zero</div>
</React.Fragment>
);
}

Dynamic class name

1
2
3
4
5
6
7
8
9
10
11
12
13
render() {
return (
<React.Fragment>
<div className={this.getBadgeClasses()}>
Zero
</div>
);
}
getBadgeClasses() {
let classes = 'badge m-2 badge-';
classes += this.state.count === 0 ? 'warning' : 'primary';
return classes;
}

For loop

1
2
3
state = {
tags: ['tag1', 'tag2', 'tag3']
};
1
2
3
4
5
<ul>
{this.state.tags.map(tag => (
<li>{tag}</li>
))}
</ul>

Add key:

1
2
3
4
5
<ul>
{this.state.tags.map(tag => (
<li key={tag}>{tag}</li>
))}
</ul>

or

It there is more than one parameter, add ( )

1
2
3
4
5
<ul>
{this.state.tags.map((tag, index) => (
<li key={index}>{tag}</li>
))}
</ul>

Render after if

If return more one line, add ( )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
render() {
return (
<React.Fragment>
{this.renderTags()}
</React.Fragment>
);
}

renderTags() {
if (this.state.tags.length === 0)
return <p>No tasgs</p>;

return (
<ul>
{this.state.tags.map((tag, index) => (
<li key={index}>{tag}</li>
))}
</ul>
);
}

Expression &&

1
2
3
4
5
6
7
8
render() {
return (
<React.Fragment>
{this.renderTags()}
{this.state.tags.length !== 0 && 'There are tags'}
</React.Fragment>
);
}

Event

onClick, not onclick

1
2
3
4
5
<button onClick={this.handleIncrement}>Increcement</button>

handleIncrement(e) {
console.log(e);
}

Event need to be sent function without parameter

Right:

1
<button onClick={this.handleIncrement}>

Wrong:

1
2
//this.handleIncrement ( 1 ) is not a functon
<button onClick={this.handleIncrement ( 1 ) }>

Right:

1
2
3
4
5
6
7
8
9
<button onClick={this.doHandleIncrecement }>

doHandleIncrecement=()=>{
this.handleIncrement({id: 1})

}
handleIncrement = (item) => {
console.log(item.id);
};

Right ( recommend ) :

1
2
3
4
5
<button onClick={() => this.handleIncrement({ id: 1 })}>

handleIncrement = item => {
console.log(item.id);
};

this, constructor()

We can’t call this in function:

1
2
3
handleIncrement() {
console.log(this);
}

Use constructor() to bind this,

1
2
3
4
5
6
7
8
9
constructor() {
super();
console.log(this);
this.handleIncrement = this.handleIncrement.bind(this);
}

handleIncrement(e) {
console.log(this);
}

Or use Arrow Function

1
2
3
handleIncrement = () => {
console.log(this);
};

Updating state

State: starts with a default value when a Component mounts and then suffers from mutations in time. It is not advisable to store anything in a state that can be derived from props at any point in time

1
2
3
handleIncrement = () => {
this.setState({ count: this.state.count + 1 });
};

this.state.count++ dosen’t work

Passing data to components

Props: (short for properties) are a Component’s configuration. They are received from above and immutable.

src/components/counters.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Counter from './counter';

class Counters extends Component {
state = {
counInfo: [{ id: 1, val: 0 }, { id: 2, val: 5 }, { id: 3, val: 2 }]
};
render() {
return (
<div>
{this.state.counInfo.map((item, index) => (
<Counter key={index} id={item.id} value={item.val} />
))}
</div>
);
}
}

export default Counters;

src/components/counter.jsx

1
2
3
4
render() {
console.log('props', this.props);
return ();
}

Use props data in src/components/counter.jsx:
Put state in constructor():

1
2
3
4
5
6
7
8
9
10
// passing in props
constructor(props) {
super();

// in constructor(), state need this,props dosen't need this
this.state = {
count: props.value,
tags: ['tag1', 'tag2', 'tag3']
};
}

Passing children

src/components/counters.jsx

1
2
3
4
5
{this.state.counInfo.map((item, index) => (
<Counter key={index} id={item.id} value={item.val}>
<h4>title</h4>
</Counter>
))}

src/components/counter.jsx

1
2
3
4
5
6
7
8
9
10
render() {
console.log('props', this.props);

return (
<div>
...
{this.props.children}
</div>
);
}

React Developer Tools

Refresh after installation, you can change the order:

1

Props VS State

  • props: passing data, can’t be modified

  • state: local, can’t be visited by other components

Passing function

src/components/counters.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
render() {
return (
<div>
..
<Counter
...
onDelete={this.handleDelete}
></Counter>
..
</div>
);
}

handleDelete = () => {
console.log('Handle delete ');
};

src/components/counter.jsx

1
<button onClick={this.props.onDelete}>Delete</button>

filter (Delete function)

src/components/counter.jsx

1
2
3
4
{/*  delete btn */}
<button
onClick={() => this.props.onDelete(this.props.id)}
>

src/components/counters.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
<Counter
...
onDelete={this.handleDelete}
id={item.id}
>

handleDelete = countId => {
const counInfo = this.state.counInfo.filter(c => c.id !== countId);

// this.setState({ counInfo: countInfo });
// we can omit the variable when the state parameter name is the same as the variable name
this.setState({ counInfo });
};

Removing local state

The state init only once when the component created, so it can’t update when the props changes

1
2
3
this.state = {
count: props.value
};

So, if want use the updating props data, deal the props in original component:

src/components/counter.jsx, use props instead of state :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{/* 增加按钮 */}
<button
onClick={() => this.props.onIncrece(this.props.item)}
>
getBadgeClasses() {
let classes = 'badge m-2 badge-';
classes += this.props.item.val === 0 ? 'warning' : 'primary';
return classes;
}

formatCount() {
const count = this.props.item.val;
return count == 0 ? 'Zero' : count;
}

src/components/counters.jsx, do increment in counters.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Counter
...
onIncrece={this.handleIncrement}
>

handleIncrement = item => {
// 拷贝statecounters
const countInfo = [...this.state.countInfo];
const index = countInfo.indexOf(item);
countInfo[index] = { ...item };
countInfo[index].val++;

this.setState({ countInfo });
};

展开语法(Spread syntax),扩展运算符是三个点(…)。用于取出参数对象的所有可遍历属性,然后拷贝到当前对象之中
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax > https://www.cnblogs.com/it-Ren/p/10637904.html >

Life cycle

order: constructor > render > componentDidMount

  • componentDidMount: After render, often initial ajax
  • componentDidUpdate: after component updated, such as state, new props,often write ajax to get new data
  • componentWillMount: before component removed, such as delete a component

Can check prevProps , prevState in componentDidUpdate:

1
2
3
4
5

componentDidUpdate(prevProps, prevState) {
console.log('prevProps', prevProps);
console.log('prevState', prevState);
}

Exchange blogroll: http://laker.me/blog
Github:https://github.com/younglaker


React Learning Record

本文原创自http://laker.me/blog,转载请注明出处,欢迎交换友链

如果本文对您有帮助,微信扫一扫,请我吃个鸡腿吧