React Patterns

React 开发者的模式。「Patterns for React Developers」

Github stars Tracking Chart

Contents

Stateless function

Stateless functions are a brilliant way to define highly reusable components. They don't hold state; they're just functions.

const Greeting = () => <div>Hi there!</div>

They get passed props and context.

const Greeting = (props, context) =>
  <div style={{color: context.color}}>Hi {props.name}!</div>

They can define local variables, where a function block is used.

const Greeting = (props, context) => {
  const style = {
    fontWeight: "bold",
    color: context.color,
  }

  return <div style={style}>{props.name}</div>
}

But you could get the same result by using other functions.

const getStyle = context => ({
  fontWeight: "bold",
  color: context.color,
})

const Greeting = (props, context) =>
  <div style={getStyle(context)}>{props.name}</div>

They can have defined defaultProps, propTypes and contextTypes.

Greeting.propTypes = {
  name: PropTypes.string.isRequired
}
Greeting.defaultProps = {
  name: "Guest"
}
Greeting.contextTypes = {
  color: PropTypes.string
}

JSX spread attributes

Spread Attributes is a JSX feature. It's syntactic sugar for passing all of an object's properties as JSX attributes.

These two examples are equivalent.

// props written as attributes
<main className="main" role="main">{children}</main>

// props "spread" from object
<main {...{className: "main", role: "main", children}} />

Use this to forward props to underlying components.

const FancyDiv = props =>
  <div className="fancy" {...props} />

Now, I can expect FancyDiv to add the attributes it's concerned with as well as those it's not.

<FancyDiv data-id="my-fancy-div">So Fancy</FancyDiv>

// output: <div class="fancy" data-id="my-fancy-div">So Fancy</div>

Keep in mind that order matters. If props.className is defined, it'll clobber the className defined by FancyDiv

<FancyDiv className="my-fancy-div" />

// output: <div className="my-fancy-div"></div>

We can make FancyDivs className always "win" by placing it after the spread props ({...props}).

// my `className` clobbers your `className`
const FancyDiv = props =>
  <div {...props} className="fancy" />

You should handle these types of props gracefully. In this case, I'll merge the author's props.className with the className needed to style my component.

const FancyDiv = ({ className, ...props }) =>
  <div
    className={["fancy", className].join(' ')}
    {...props}
  />

destructuring arguments

Destructuring assignment is an ES2015 feature. It pairs nicely with props in Stateless Functions.

These examples are equivalent.

const Greeting = props => <div>Hi {props.name}!</div>

const Greeting = ({ name }) => <div>Hi {name}!</div>

The rest parameter syntax (...) allows you to collect all the remaining properties in a new object.

const Greeting = ({ name, ...props }) =>
  <div>Hi {name}!</div>

In turn, this object can use JSX Spread Attributes to forward props to the composed component.

const Greeting = ({ name, ...props }) =>
  <div {...props}>Hi {name}!</div>

Avoid forwarding non-DOM props to composed components. Destructuring makes this very easy because you can create a new props object without component-specific props.

conditional rendering

You can't use regular if/else conditions inside a component definition. The conditional (ternary) operator is your friend.

if

{condition && <span>Rendered when `truthy`</span> }

unless

{condition

Main metrics

Overview
Name With Ownerchantastic/reactpatterns
Primary LanguageHTML
Program languageHTML (Language Count: 2)
PlatformWeb browsers
License:
所有者活动
Created At2016-08-18 17:20:27
Pushed At2022-01-15 01:23:45
Last Commit At2020-01-08 20:06:29
Release Count0
用户参与
Stargazers Count1.7k
Watchers Count60
Fork Count99
Commits Count96
Has Issues Enabled
Issues Count22
Issue Open Count5
Pull Requests Count20
Pull Requests Open Count2
Pull Requests Close Count5
项目设置
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private