React 7
7.86 Deeper into Components and React Internals
import React, { Component } from 'react';
import './App.css';
import Persons from '../components/Persons/Persons';
import Cockpit from '../components/Cockpit/Cockpit';
//use as many as function components as possible
//containers be as lean as possible
class App extends Component {
state = {
persons: [
{id:'1', name: 'Max', age: 28 },
{id:'2', name: 'Manu', age: 29 },
{id:'3', name: 'Stephanie', age: 26 }
],
otherState: 'some other value',
showPersons: false
}
switchNameHandler = (newName) => {
// console.log('Was clicked!');
// DON'T DO THIS: this.state.persons[0].name = 'Maximilian';
this.setState( {
persons: [
{name: newName, age: 28 },
{name: 'Manu', age: 29 },
{name: 'Stephanie', age: 27 }
]
} )
}
nameChangedHandler = (event, id) => {
const personIndex = this.state.persons.findIndex(p => {
return p.id === id;//这个看不懂
});
const person = { ...this.state.persons[personIndex] };
person.name = event.target.value;
const persons = [...this.state.persons];
persons[personIndex] = person;
this.setState({
persons: persons
});
}
togglePersonsHandler = () => {
const doesShow = this.state.showPersons;
this.setState({showPersons: !doesShow});
}
deletePersonHandler = (personIndex) => {
const persons = this.state.persons.slice();
//const persons = [...this.state.persons];
persons.splice(personIndex, 1);
this.setState({ persons: persons });///bhb
}
render() {
let persons = null;
if(this.state.showPersons){
persons = <Persons
persons={this.state.persons}
clicked={this.deletePersonHandler}
changed={this.nameChangedHandler}
/>
;
return (
<div className="App">
<Cockpit
showPersons={this.state.showPersons}
persons={this.state.persons}
clicked={this.togglePersonsHandler}
/>
{persons}
</div>
);
// return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?'));
}
}
export default App;
import React from 'react'; //import '.../containers/App.css' import styled from 'styled-components'; const cockpit = (props) => { const StyledButton = styled.button` background-color: ${props => props.alt ? 'red' : 'green'}; color: white; font: inherit; border: 1px solid blue; padding: 8px; cursor: pointer; &:hover { background-color: ${props => props.alt ? 'blue' : 'salmon'}; color: black; } `; let classes = []; if (props.persons.length <= 2) { classes.push('red');//push red 给这个array } if (props.persons.length <= 1) { classes.push('bold'); } return ( <div> <h1>Hi, I'm a React App</h1> <p className={classes.join(' ')}>This is really working!</p> <StyledButton alt={props.showPersons} onClick={props.clicked}>Switch Name</StyledButton> </div>); }; //报错:return multiple outputs without root node(用《div》括起来) export default cockpit;
87 stateful stateless
presentational state(stateless)a functional components dont use state

index.js
ReactDOM.render(<App appTitle="Person Manager"/>, document.getElementById('root'));



89 class component lifecycle



change functional component into class based component
import React from 'react'; /*import './Person.css';*/ /*import Radium from 'radium';*/ import styled from 'styled-components'; const StyledDiv = styled.div` width:60%; margin:16px; border:1px solid #eee; box-shadow: 0 2px 3px #ccc; padding: 16px; text-align: center; `; const person = ( props ) => { return ( /*<div className="Person">*/ <StyledDiv> <p onClick={props.click}>I'm {props.name} and I am {props.age} years old!</p> <p>{props.children}</p> <input type="text" onChange={props.changed} value={props.name} /> </StyledDiv> ) }; export default person;
useEffect() in functional components
useEffect(() => { console.log("cockpitjs useEffect"); });
useeffect 一直会render
下面只有persons change了 才会rerender 如果是【】则只有第一次和unmount时生效
useEffect(() => { console.log("cockpitjs useEffect"); setTimeout(() => { alert("saved"); }, 1000); 一秒后有个alert 测试用 }, [props.persons]);//当什么元素执行的时候 如果数组里没有元素 则只有第一次render //useEffect(可以加其他的effect)
return代表componentwillunmount 即这个组件被remove了那就会有console.log 但是除非它被remove 否则一直不会有log(在first render cycle 以后 但其他之前)
return () => { /* clearTimeout(timer);*/ console.log("cockpit js cleanup");//this is not shown because cockpit is never removed? };
搞清楚 real dom virtual dom render
7.97 class-based:shouldConponentUpdate
shouldComponentUpdate(nextProps, nextState) { console.log("shouldComponentUpdate personjs"); if (nextProps !== this.props) { return true; } else { return false; }
如果有改动,就重新render
7.98 Optimizing Functional Components
with React.memo()
if (props.personslength <= 1) { classes.push('bold'); }
export default React.memo(cockpit);
if use memo only rerender when props change

there is no

7.100
import React, { Component} from 'react';
import styled from 'styled-components';
class Person extends Component {//大写class name
static getDerivedStateFromProps(props, state) {
console.log("getDerivedStateFromProps personjs");
return state;
}
shouldComponentUpdate(nextProps, nextState) {
console.log("shouldComponentUpdate personjs");
if (nextProps !== this.props ||
nextProps.changed !==this.props.changed
) {
return true;
} else {
return false;
}
等于
import React, { PureComponent} from 'react';
/*import './Person.css';*/
/*import Radium from 'radium';*/
import styled from 'styled-components';
class Person extends PureComponent {
自带shouldComponentUpdate 查重所有props
7.101

102 Rendering Adjacent JSX Elements
<Div>
<p onClick={this.props.click}>I'm {this.props.name} and I am {this.props.age} years old!</p>
<p>{this.props.children}</p>
<input type="text" onChange={this.props.changed} value={this.props.name} />
</Div>//props前加上this
==
【 <p key=“1” onClick={this.props.click}>I'm {this.props.name} and I am {this.props.age} years old!</p>, <p key=“2”>{this.props.children}</p>, <input key=“3” type="text" onChange={this.props.changed} value={this.props.name} /> 】




HOC



107 passing unknown props
person.js
import React, { Component } from 'react'; import Aux from '../../../hoc/Auxillary'; import withClass from '../../../hoc/withClass'; import classes from './Person.css'; class Person extends Component { render() { console.log('[Person.js] rendering...'); return ( <Aux> <p onClick={this.props.click}> I'm {this.props.name} and I am {this.props.age} years old! </p> <p key="i2">{this.props.children}</p> <input key="i3" type="text" onChange={this.props.changed} value={this.props.name} /> </Aux> ); } } export default withClass(Person, classes.Person);
withClass.js
import React from 'react'; const withClass = (WrappedComponent, className) => { return props => ( <div className={className}> <WrappedComponent {...props}/> </div> ); }; export default withClass;
aux.js
const aux = props => props.children; export default aux;
108.setState correctly

用这个而不是

因为这个不能保证this.state是上一个state
109:Using PropTypes
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Aux from '../../../hoc/Auxillary';
import withClass from '../../../hoc/withClass';
import classes from './Person.css';
class Person extends Component {
render() {
console.log('[Person.js] rendering...');
return (
<Aux>
<p onClick={this.props.click}>
I'm {this.props.name} and I am {this.props.age} years old!
</p>
<p key="i2">{this.props.children}</p>
<input
key="i3"
type="text"
onChange={this.props.changed}
value={this.props.name}
/>
</Aux>
);
}
}
Person.propTypes = {
click: PropTypes.func,
name: PropTypes.string,
age: PropTypes.number,
changed: PropTypes.func
};
export default withClass(Person, classes.Person);
类型检查,没有符合,加warning
110 using ref
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Aux from '../../../hoc/Auxillary';
import withClass from '../../../hoc/withClass';
import classes from './Person.css';
class Person extends Component {
componentDidMount() {
this.inputElement.focus();
}
render() {
console.log('[Person.js] rendering...');
return (
<Aux>
<p onClick={this.props.click}>
I'm {this.props.name} and I am {this.props.age} years old!
</p>
<p key="i2">{this.props.children}</p>
<input
key="i3"
ref={(inputEl) => {this.inputElement=inputEl }}
type="text"
onChange={this.props.changed}
value={this.props.name}
/>
</Aux>
);
}
}
Person.propTypes = {
click: PropTypes.func,
name: PropTypes.string,
age: PropTypes.number,
changed: PropTypes.func
};
export default withClass(Person, classes.Person);
111 ref with react hook
import React, { useEffect,useRef } from 'react';
import classes from './Cockpit.css';
const Cockpit = props => {
const toggleBtnRef = React.createRef(null);
/*toggleBtnRef.current.click();*/
useEffect(() => {
console.log('[Cockpit.js] useEffect');
// Http request...
/*setTimeout(() => {
alert('Saved data to cloud!');
}, 1000);*/
toggleBtnRef.current.click();
return () => {
console.log('[Cockpit.js] cleanup work in useEffect');
};
}, []);
useEffect(() => {
console.log('[Cockpit.js] 2nd useEffect');
return () => {
console.log('[Cockpit.js] cleanup work in 2nd useEffect');
};
});
// useEffect();
const assignedClasses = [];
let btnClass = '';
if (props.showPersons) {
btnClass = classes.Red;
}
if (props.personsLength <= 2) {
assignedClasses.push(classes.red); // classes = ['red']
}
if (props.personsLength <= 1) {
assignedClasses.push(classes.bold); // classes = ['red', 'bold']
}
return (
<div className={classes.Cockpit}>
<h1>{props.title}</h1>
<p className={assignedClasses.join(' ')}>This is really working!</p>
<button ref={toggleBtnRef} className={btnClass} onClick={props.clicked}>
Toggle Persons
</button>
</div>
);
};
export default React.memo(Cockpit);
不能放在上面 放在上面 渲染时候下面jsx代码还没有渲染 会报错,故放在useffect里 在render结束后发生
functional component只能用这个react hook
浙公网安备 33010602011771号