Junfeng Liu
2018-05-11
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
// Short syntax available in Babel v7.0.0-beta.31+
class Columns extends React.Component {
render() {
return (
<>
<td>Hello</td>
<td>World</td>
</>
);
}
}
render() {
// React does *not* create a new div. It renders the children into `domNode`.
// `domNode` is any valid DOM node, regardless of its location in the DOM.
return ReactDOM.createPortal(
this.props.children,
domNode,
);
}
Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
const ThemeContext = React.createContext('light');
class ThemeProvider extends React.Component {
state = {theme: 'light'};
render() {
return (
<ThemeContext.Provider value={this.state.theme}>
{this.props.children}
</ThemeContext.Provider>
);
}
}
class ThemedButton extends React.Component {
render() {
return (
<ThemeContext.Consumer>
{theme => <Button theme={theme} />}
</ThemeContext.Consumer>
);
}
}
function ppHOC(WrappedComponent) {
return class PP extends React.Component {
render() {
const newProps = {
user: currentLoggedInUser
}
return <WrappedComponent {...this.props} {...newProps}/>
}
}
}
function iiHOC(WrappedComponent) {
return class Enhancer extends WrappedComponent {
render() {
if (this.props.loggedIn) {
return super.render()
} else {
return null
}
}
}
}
function HOCFactoryFactory(...params){
// do something with params
return function HOCFactory(WrappedComponent) {
return class HOC extends React.Component {
render() {
return <WrappedComponent {...this.props}/>
}
}
}
}
HOCFactoryFactory(params)(WrappedComponent)
const Foo = ({ children }) => {
return children('foo');
};
<Foo>
{(name) => <div>`hello from ${name}`</div>}
</Foo>
const Foo = ({ hello }) => {
return hello('foo');
};
const hello = (name) => {
return <div>`hello from ${name}`</div>;
};
<Foo hello={hello} />
const Foo = ({ Hello }) => {
return <Hello name="foo" />;
};
const Hello = ({ name }) => {
return <div>`hello from ${name}`</div>;
};
<Foo Hello={Hello} />
setState(stateChange[, callback])
this.setState({quantity: 2});
performs a shallow merge of stateChange into the new state
setState(updater[, callback])
this.setState((prevState, props) => {
return {counter: prevState.counter + props.step};
});
updater is a function with the signature:
(prevState, props) => stateChange
function increase (state, props) {
return {value : state.value + props.step};
}
function decrease (state, props) {
return {value : state.value - props.step};
}
class Counter extends Component {
state = {value: 0};
handleIncrement = () => {
this.setState(increase);
}
handleDecrement = () => {
this.setState(decrease);
}
render() {
return (
<div>
<button onClick={this.handleIncrement}>+</button>
<h1>{this.state.value}</h1>
<button onClick={this.handleDecrement}>-</button>
</div>
);
}
}
Declare state changes separately from the component classes.
写 CSS 代码时都有哪些痛点:
import React from 'react';
import styled, { css } from 'styled-components';
// Create a <Title> react component
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
// Create a <Wrapper> react component that renders a <section> with
// some padding and a papayawhip background
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
// Use them like any other React component – except they're styled!
<Wrapper>
<Title>Hello World, this is my first styled component!</Title>
</Wrapper>
const Button = styled.button`
border-radius: 3px;
padding: 0.25em 1em;
margin: 0 1em;
background: transparent;
color: palevioletred;
border: 2px solid palevioletred;
${props => props.primary && css`
background: palevioletred;
color: white;
`}
`;
const Link = ({ className, children }) => (
<a className={className}>
{children}
</a>
)
const StyledLink = styled(Link)`
color: palevioletred;
font-weight: bold;
`;
render(
<div>
<Link>Unstyled, boring Link</Link>
<br />
<StyledLink>Styled, exciting Link</StyledLink>
</div>
);
https://www.styled-components.com/
名称 | 大小 (gzip) | 特点 |
---|---|---|
React | 49KB | |
Preact | 3KB | 体积小,高性能,兼容 IE9+ |
Inferno | 8KB | 高性能,无状态组件支持生命期事件 |
react-lite | 13KB | 对 React 的兼容程度高,只支持 JSX |
Nerv | 9KB | 京东开发,高性能,兼容 IE8 |
{
resolve: {
alias: {
'react': 'nervjs',
'react-dom': 'nervjs'
}
}
}
{
"plugins": [
["module-resolver", {
"root": ["."],
"alias": {
"react": "nervjs",
"react-dom": "nervjs"
}
}]
]
}
yarn global add parcel-bundler
parcel index.html
yarn add --dev parcel-bundler
// package.json
"scripts": {
"start": "parcel index.html",
"build": "parcel build index.html"
}
yarn start
<html>
<body>
<script src="./index.js"></script>
</body>
</html>
index.html
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import Button from '../components/Button';
storiesOf('Button', module)
.add('with text', () => (
<Button onClick={action('clicked')}>Hello Button</Button>
))
.add('with some emoji', () => (
<Button onClick={action('clicked')}>
<span role="img" aria-label="so cool">😀 😎 👍 💯</span>
</Button>
));