# 处理组件报错

react 组件错误边界

在 `development` 模式下，如果程序出错，将会弹出一个错误栈，发布模式下不做UI变化，仅处理 `onError`

## 使用案例

## 案例演示

### 基本使用

> 搜索框中，输入 `a` 则引发错误。

---demo
```js
import { ErrorBoundary, Checkbox  } from 'amos-framework';

const { errorHandlerConnect, withErrorHandler } = ErrorBoundary.$components

const datas = [
  { id: 1, title: '张三', descr: '很长很长的描述文字', stress: true },
  { id: 2, title: '李四', descr: '很长很长的描述文字', stress: false },
  { id: 3, title: '王五', descr: '很长很长的描述文字', stress: false },
  { id: 4, title: 'ilex', descr: '很长很长的描述文字', stress: false },
  { id: 5, title: 'iray', descr: '很长很长的描述文字', stress: true },
  { id: 6, title: '王二', descr: '很长很长的描述文字', stress: true },
];

class ListDemo extends Component {
  getDatas = () => {
    const { filterText, onlyStress, datas } = this.props;
    if (filterText === 'a') {
      // 触发错误
      throw new Error('Page crashed! (Test Error Boundaries when input "a")');
    }
    const newDatas = [];

    console.log('filter:' + filterText, 'onlyStress:' + onlyStress)

    datas.forEach((item) => {
      if (item.title.indexOf(filterText) === -1 || (!item.stress && onlyStress)) {
        return;
      }
      newDatas.push(item);
    });

    return newDatas;
  }

  render() {
    return (
      <List
        itemLayout="horizontal"
        dataSource={this.getDatas()}
        renderItem={item => (
          <List.Item>
            <List.Item.Meta
              avatar={<Avatar src="https://tinypng.com/images/panda-chewing.png" />}
              title={item.stress ? <span style={{ color: 'red' }}>{item.title}</span> : item.title}
              description={item.descr}
            />
          </List.Item>
        )}
      />
    );
  }
}

class SearchBar extends Component {
  render() {
    const { onFilterTextInput, onInStockInput, filterText, onlyStress } = this.props;
    return (
      <div style={{ display: 'flex' }}>
        <Checkbox checked={onlyStress} onChange={(e) => onInStockInput(e.target.checked)}>只显示强调</Checkbox >
        <Search icon="search" value={filterText} onChange={(e) => onFilterTextInput(e.target.value)} />
      </div>
    );
  }
}

// @errorHandlerConnect
class TestTable extends Component {

  constructor(props) {
    super(props);
    this.state = {
      filterText: '',
      onlyStress: false
    };
  }

  handleFilterTextInput = (filterText) => {
    this.setState({
      filterText: filterText
    });
  }

  handleInStockInput = (onlyStress) => {
    this.setState({
      onlyStress: onlyStress
    })
  }

  render() {
    const {} = this.state;
    return (
      <div style={{ width: '25em' }}>
        <SearchBar
          filterText={this.state.filterText}
          onlyStress={this.state.onlyStress}
          onFilterTextInput={this.handleFilterTextInput}
          onInStockInput={this.handleInStockInput}
        />
        <ListDemo
          datas={datas}
          filterText={this.state.filterText}
          onlyStress={this.state.onlyStress}
        />
      </div>
    );
  }
}

function onError(error, errorInfo, props) {
  console.warn('errordemo.onError:', error, errorInfo, props);
}

const Demo = () => (
  <ErrorBoundary onError={onError}>
    <TestTable onError={onError} />
  </ErrorBoundary>
);

ReactDOM.render(<Demo />, _react_runner_);
```
---demoend

### 未使用错误边界情况

> 搜索框中，输入 `a` 则引发错误。将会导致该模块白屏，示例中所有节点会销毁（devtools 中进行查看）。

---demo
```js
import { ErrorBoundary, Checkbox  } from 'amos-framework';

const { errorHandlerConnect, withErrorHandler } = ErrorBoundary.$components

const datas = [
  { id: 1, title: '张三', descr: '很长很长的描述文字', stress: true },
  { id: 2, title: '李四', descr: '很长很长的描述文字', stress: false },
  { id: 3, title: '王五', descr: '很长很长的描述文字', stress: false },
  { id: 4, title: 'ilex', descr: '很长很长的描述文字', stress: false },
  { id: 5, title: 'iray', descr: '很长很长的描述文字', stress: true },
  { id: 6, title: '王二', descr: '很长很长的描述文字', stress: true },
];

class ListDemo extends Component {
  getDatas = () => {
    const { filterText, onlyStress, datas } = this.props;
    if (filterText === 'a') {
      // 触发错误
      throw new Error('Page crashed! (Test Error Boundaries when input "a")');
    }
    const newDatas = [];

    console.log('filter:' + filterText, 'onlyStress:' + onlyStress)

    datas.forEach((item) => {
      if (item.title.indexOf(filterText) === -1 || (!item.stress && onlyStress)) {
        return;
      }
      newDatas.push(item);
    });

    return newDatas;
  }

  render() {
    return (
      <List
        itemLayout="horizontal"
        dataSource={this.getDatas()}
        renderItem={item => (
          <List.Item>
            <List.Item.Meta
              avatar={<Avatar src="https://tinypng.com/images/panda-chewing.png" />}
              title={item.stress ? <span style={{ color: 'red' }}>{item.title}</span> : item.title}
              description={item.descr}
            />
          </List.Item>
        )}
      />
    );
  }
}

class SearchBar extends Component {
  render() {
    const { onFilterTextInput, onInStockInput, filterText, onlyStress } = this.props;
    return (
      <div style={{ display: 'flex' }}>
        <Checkbox checked={onlyStress} onChange={(e) => onInStockInput(e.target.checked)}>只显示强调</Checkbox >
        <Search icon="search" value={filterText} onChange={(e) => onFilterTextInput(e.target.value)} />
      </div>
    );
  }
}

class TestTable extends Component {

  constructor(props) {
    super(props);
    this.state = {
      filterText: '',
      onlyStress: false
    };
  }

  handleFilterTextInput = (filterText) => {
    this.setState({
      filterText: filterText
    });
  }

  handleInStockInput = (onlyStress) => {
    this.setState({
      onlyStress: onlyStress
    })
  }

  render() {
    const {} = this.state;
    return (
      <div style={{ width: '25em' }}>
        <SearchBar
          filterText={this.state.filterText}
          onlyStress={this.state.onlyStress}
          onFilterTextInput={this.handleFilterTextInput}
          onInStockInput={this.handleInStockInput}
        />
        <ListDemo
          datas={datas}
          filterText={this.state.filterText}
          onlyStress={this.state.onlyStress}
        />
      </div>
    );
  }
}

function onError(error, errorInfo, props) {
  console.warn('errordemo.onError:', error, errorInfo, props);
}

const Demo = () => <TestTable onError={onError} />;

ReactDOM.render(<Demo />, _react_runner_);
```
---demoend

### 使用HOC

> 搜索框中，输入 `a` 则引发错误。

---demo
```js
import { ErrorBoundary, Checkbox  } from 'amos-framework';

const { errorHandlerConnect, withErrorHandler } = ErrorBoundary.$components

const datas = [
  { id: 1, title: '张三', descr: '很长很长的描述文字', stress: true },
  { id: 2, title: '李四', descr: '很长很长的描述文字', stress: false },
  { id: 3, title: '王五', descr: '很长很长的描述文字', stress: false },
  { id: 4, title: 'ilex', descr: '很长很长的描述文字', stress: false },
  { id: 5, title: 'iray', descr: '很长很长的描述文字', stress: true },
  { id: 6, title: '王二', descr: '很长很长的描述文字', stress: true },
];

class ListDemo extends Component {
  getDatas = () => {
    const { filterText, onlyStress, datas } = this.props;
    if (filterText === 'a') {
      // 触发错误
      throw new Error('Page crashed! (Test Error Boundaries when input "a")');
    }
    const newDatas = [];

    console.log('filter:' + filterText, 'onlyStress:' + onlyStress)

    datas.forEach((item) => {
      if (item.title.indexOf(filterText) === -1 || (!item.stress && onlyStress)) {
        return;
      }
      newDatas.push(item);
    });

    return newDatas;
  }

  render() {
    return (
      <List
        itemLayout="horizontal"
        dataSource={this.getDatas()}
        renderItem={item => (
          <List.Item>
            <List.Item.Meta
              avatar={<Avatar src="https://tinypng.com/images/panda-chewing.png" />}
              title={item.stress ? <span style={{ color: 'red' }}>{item.title}</span> : item.title}
              description={item.descr}
            />
          </List.Item>
        )}
      />
    );
  }
}

class SearchBar extends Component {
  render() {
    const { onFilterTextInput, onInStockInput, filterText, onlyStress } = this.props;
    return (
      <div style={{ display: 'flex' }}>
        <Checkbox checked={onlyStress} onChange={(e) => onInStockInput(e.target.checked)}>只显示强调</Checkbox >
        <Search icon="search" value={filterText} onChange={(e) => onFilterTextInput(e.target.value)} />
      </div>
    );
  }
}

class TestTable extends Component {

  constructor(props) {
    super(props);
    this.state = {
      filterText: '',
      onlyStress: false
    };
  }

  handleFilterTextInput = (filterText) => {
    this.setState({
      filterText: filterText
    });
  }

  handleInStockInput = (onlyStress) => {
    this.setState({
      onlyStress: onlyStress
    })
  }

  render() {
    const {} = this.state;
    return (
      <div style={{ width: '25em' }}>
        <SearchBar
          filterText={this.state.filterText}
          onlyStress={this.state.onlyStress}
          onFilterTextInput={this.handleFilterTextInput}
          onInStockInput={this.handleInStockInput}
        />
        <ListDemo
          datas={datas}
          filterText={this.state.filterText}
          onlyStress={this.state.onlyStress}
        />
      </div>
    );
  }
}

function onError(error, errorInfo, props) {
  console.warn('errordemo.onError:', error, errorInfo, props);
}

const Demo = errorHandlerConnect(TestTable);

ReactDOM.render(<Demo onError={onError} />, _react_runner_);
```
---demoend
