jsx Pupster Alert

pupsterAlert
<div className="alert alert-success" role="alert">
  Your alert message here!
</div>

jsx Pupster Like / Dislike Buttons

pupsterButtons
<p>
    <button type="button" className="btn btn-primary mr-2">Like</button>
    <button type="button" className="btn btn-secondary">Dislike</button>
</p>

jsx Pupster NavBar

pupsterNavReactified
import React from "react";
import { Link, NavLink } from "react-router-dom";

const NavBar = () => {
    return (
        <nav className="navbar navbar-expand-lg navbar-dark bg-dark">
            <Link className="navbar-brand" to="/">Pupster</Link>
            <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
                <span className="navbar-toggler-icon"></span>
            </button>
            <div className="collapse navbar-collapse" id="navbarNav">
                <ul className="navbar-nav">
                    <li>
                        <NavLink 
                            activeClassName="active"
                            className="nav-link" 
                            isActive={() => window.location.pathname === "/" || window.location.pathname === "/about"}
                            to="/"
                        >
                            About
                        </NavLink>
                    </li>
                    <li>
                        <NavLink 
                            activeClassName="active"
                            className="nav-link" 
                            isActive={() => window.location.pathname === "/discover"}
                            to="/discover"
                        >
                            Discover
                        </NavLink>
                    </li>
                    <li>
                        <NavLink 
                            activeClassName="active"
                            className="nav-link" 
                            isActive={() => window.location.pathname === "/search"}
                            to="/search"
                        >
                            Search
                        </NavLink>
                    </li>
                </ul>
            </div>
        </nav>
    )
}

export default NavBar;
pupsterNav
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
    <a class="navbar-brand" href="/">Pupster</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNav">
        <ul class="navbar-nav">
            <li class="nav-link">
                <a class="nav-link" href="/">About</a>
            </li>
            <li class="nav-link">
                <a class="nav-link" href="/discover">Discover</a>
            </li>
            <li class="nav-link">
                <a class="nav-link" href="/search">Search</a>
            </li>
        </ul>
    </div>
</nav>

jsx 风格装载机

命名你的css文件------ name.module.scss <br/>

app.js
import styles from './App.module.scss';

jsx Slate API

Slate API发现

1.js
if (event.key == 'Enter' && value.startBlock.type == 'check-list-item') {
  editor.splitBlock().setBlocks({ data: { checked: false } })
  return
}
2.js
if (
  event.key == 'Backspace' &&
  value.isCollapsed &&
  value.startBlock.type == 'check-list-item' &&
  value.selection.startOffset == 0
) {
  editor.setBlocks('paragraph')
  return
}
3.js
if (event.key === 'Enter' && startBlock.type === 'code') {
  editor.insertText('\n')
  return
}
markdown-shortcuts.js
import { Editor } from 'slate-react'
import { Value } from 'slate'

import React from 'react'
import initialValueAsJson from './value.json'

/**
 * Deserialize the initial editor value.
 *
 * @type {Object}
 */

const initialValue = Value.fromJSON(initialValueAsJson)

/**
 * The auto-markdown example.
 *
 * @type {Component}
 */

class MarkdownShortcuts extends React.Component {
  /**
   * Get the block type for a series of auto-markdown shortcut `chars`.
   *
   * @param {String} chars
   * @return {String} block
   */

  getType = chars => {
    switch (chars) {
      case '*':
      case '-':
      case '+':
        return 'list-item'
      case '>':
        return 'block-quote'
      case '#':
        return 'heading-one'
      case '##':
        return 'heading-two'
      case '###':
        return 'heading-three'
      case '####':
        return 'heading-four'
      case '#####':
        return 'heading-five'
      case '######':
        return 'heading-six'
      default:
        return null
    }
  }

  /**
   *
   * Render the example.
   *
   * @return {Component} component
   */

  render() {
    return (
      <Editor
        placeholder="Write some markdown..."
        defaultValue={initialValue}
        onKeyDown={this.onKeyDown}
        renderNode={this.renderNode}
      />
    )
  }

  /**
   * Render a Slate node.
   *
   * @param {Object} props
   * @param {Editor} editor
   * @param {Function} next
   * @return {Element}
   */

  renderNode = (props, editor, next) => {
    const { attributes, children, node } = props

    switch (node.type) {
      case 'block-quote':
        return <blockquote {...attributes}>{children}</blockquote>
      case 'bulleted-list':
        return <ul {...attributes}>{children}</ul>
      case 'heading-one':
        return <h1 {...attributes}>{children}</h1>
      case 'heading-two':
        return <h2 {...attributes}>{children}</h2>
      case 'heading-three':
        return <h3 {...attributes}>{children}</h3>
      case 'heading-four':
        return <h4 {...attributes}>{children}</h4>
      case 'heading-five':
        return <h5 {...attributes}>{children}</h5>
      case 'heading-six':
        return <h6 {...attributes}>{children}</h6>
      case 'list-item':
        return <li {...attributes}>{children}</li>
      default:
        return next()
    }
  }

  /**
   * On key down, check for our specific key shortcuts.
   *
   * @param {Event} event
   * @param {Editor} editor
   * @param {Function} next
   */

  onKeyDown = (event, editor, next) => {
    switch (event.key) {
      case ' ':
        return this.onSpace(event, editor, next)
      case 'Backspace':
        return this.onBackspace(event, editor, next)
      case 'Enter':
        return this.onEnter(event, editor, next)
      default:
        return next()
    }
  }

  /**
   * On space, if it was after an auto-markdown shortcut, convert the current
   * node into the shortcut's corresponding type.
   *
   * @param {Event} event
   * @param {Editor} editor
   * @param {Function} next
   */

  onSpace = (event, editor, next) => {
    const { value } = editor
    const { selection } = value
    if (selection.isExpanded) return next()

    const { startBlock } = value
    const { start } = selection
    const chars = startBlock.text.slice(0, start.offset).replace(/\s*/g, '')
    const type = this.getType(chars)
    if (!type) return next()
    if (type == 'list-item' && startBlock.type == 'list-item') return next()
    event.preventDefault()

    editor.setBlocks(type)

    if (type == 'list-item') {
      editor.wrapBlock('bulleted-list')
    }

    editor.moveFocusToStartOfNode(startBlock).delete()
  }

  /**
   * On backspace, if at the start of a non-paragraph, convert it back into a
   * paragraph node.
   *
   * @param {Event} event
   * @param {Editor} editor
   * @param {Function} next
   */

  onBackspace = (event, editor, next) => {
    const { value } = editor
    const { selection } = value
    if (selection.isExpanded) return next()
    if (selection.start.offset != 0) return next()

    const { startBlock } = value
    if (startBlock.type == 'paragraph') return next()

    event.preventDefault()
    editor.setBlocks('paragraph')

    if (startBlock.type == 'list-item') {
      editor.unwrapBlock('bulleted-list')
    }
  }

  /**
   * On return, if at the end of a node type that should not be extended,
   * create a new paragraph below it.
   *
   * @param {Event} event
   * @param {Editor} editor
   * @param {Function} next
   */

  onEnter = (event, editor, next) => {
    const { value } = editor
    const { selection } = value
    const { start, end, isExpanded } = selection
    if (isExpanded) return next()

    const { startBlock } = value
    if (start.offset == 0 && startBlock.text.length == 0)
      return this.onBackspace(event, editor, next)
    if (end.offset != startBlock.text.length) return next()

    if (
      startBlock.type != 'heading-one' &&
      startBlock.type != 'heading-two' &&
      startBlock.type != 'heading-three' &&
      startBlock.type != 'heading-four' &&
      startBlock.type != 'heading-five' &&
      startBlock.type != 'heading-six' &&
      startBlock.type != 'block-quote'
    ) {
      return next()
    }

    event.preventDefault()
    editor.splitBlock().setBlocks('paragraph')
  }
}

/**
 * Export.
 */

export default MarkdownShortcuts

jsx router以编程方式导航

router Programmatically navigate
this.props.history.push('/dashboard')

jsx 路线和链接

Routes and links
import { BrowserRouter } from 'react-router-dom';

<BrowserRouter>
  <Layout />
</BrowserRouter>

<Link to={{
  pathname: '/new-post',
  hash: '#submit',
  search: '?quick-submit=true'
}}>New Post</Link>

//<Route path="/" render={() => <h1>Home 2</h1>} />
<Route path="/" exact component={Posts} />
<Route path="/new-post" component={NewPost} />
<Route path={this.props.match.url + '/:id'} exact component={FullPost} />

import { Switch, Route } from 'react-router'

  <Route exact path="/" component={Home}/>
<Switch>
  <Route path="/about" component={About}/>
  <Route path="/:user" component={User}/>
  <Route component={NoMatch}/>
</Switch>

jsx 列表和键

lists_and_keys
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);

const todoItems = todos.map((todo, index) =>
  // Only do this if items have no stable IDs
  <li key={index}>
    {todo.text}
  </li>
);

const content = posts.map((post) =>
  <Post
    key={post.id}
    id={post.id}
    title={post.title} />
);

function NumberList(props) {
  const numbers = props.numbers;
  return (
    <ul>
      {numbers.map((number) =>
        <ListItem key={number.toString()}
                  value={number} />

      )}
    </ul>
  );
}

jsx 反应组件组成

index.jsx
 const example = () => 
 <ProductList searchTerm={this.state.searchTerm} productList={products}
    child={(visibleProduct, key) => (
        <ProductPreview product={visibleProduct} key={key}>
            {(product) => (
                <div>
                    <AddToCart product={product} quantity={1} />
                </div>
            )}
        </ProductPreview>)}
    ArrayFadeTransition={(children) => (
        <ArrayFadeTransition children={children} />
    )}
/>
ProductList.jsx
import React, { Component } from 'react';

class ProductList extends Component {
    constructor() {
        super();
    }

    render() {
        let visibleProducts;
        let term = this.props.searchTerm;

        function searchingFor(term) {
            return function (x) {
                return x.name.toLowerCase().includes(term.toLowerCase()) || !term;
            }
        }

        visibleProducts = this.props.productList.filter(searchingFor(term)).map(product => {
            return (
                this.props.child(product, product.id)
            )
        });

        const withArrayFadeTransition = this.props.ArrayFadeTransition ?
            this.props.ArrayFadeTransition(visibleProducts) :
            visibleProducts;

        return (
            <div>
                {withArrayFadeTransition}
            </div>
        );
    }
}

export default ProductList

jsx 故事书的例子

Container.js
import { compose } from 'recompose';

...

export const CartInfoContainer = compose(
    connect(
        mapStateToProps, null
    )
)
stories.jsx
import React from 'react';
import { Provider } from 'react-redux';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { PureCartItem } from './CartItem';
import { mockedCartItem } from '../CartItemControl/CartItemControl.stories';
import { BoxDecorater } from '_helper/storybook-decorator';


// A super-simple mock of a redux store
const store = {
    getState: () => {
        return {
           
        };
    },
    subscribe: () => 0,
    dispatch: action('dispatch')
};

const props = {
    numberOfItemsInCart: 10,
};

export const actions = {
    increaseCartItemCounter: action('increaseCartItemCounter'),
};


storiesOf('CartItem', module)
    .addDecorator(story => <Provider store={store}>{story()}</Provider>)
    .addDecorator(BoxDecorater(400,400))
    .add('default', () => <PureCartItem cartItem={mockedCartItem} />);