diff --git a/README.md b/README.md index bc8ad3f..b7222c4 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,28 @@ We can add an `Else` component as the last child of `Whether` to get 2 branches. ### More branches +#### simple condition branches: perform switch and case logic + +```jsx +let testValue = 4; + + + + negative review + + + medium review + + + good review + + +``` + +You can set a `equal` function as prop for compare two values. + +#### complex condition branches + For more complex condition branches, `context` prop allows `Whether` to manage a condition context and perform more branches, you can use `Match` and its `selector` prop to create a branch. ```jsx diff --git a/src/Case.js b/src/Case.js new file mode 100644 index 0000000..dcac7b9 --- /dev/null +++ b/src/Case.js @@ -0,0 +1,18 @@ +/** + * @file 空组件,用于给`Switch`使用 + * @author daxuewen + */ + +import PropTypes from 'prop-types'; + +/* istanbul ignore next line */ +const Case = () => null; + +Case.displayName = 'Case'; + +Case.propTypes = { + children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired, + value: PropTypes.any.isRequired +}; + +export default Case; diff --git a/src/Default.js b/src/Default.js new file mode 100644 index 0000000..222a463 --- /dev/null +++ b/src/Default.js @@ -0,0 +1,17 @@ +/** + * @file 空组件,用于给`Switch`使用 + * @author daxuewen + */ + +import PropTypes from 'prop-types'; + +/* istanbul ignore next line */ +const Default = () => null; + +Default.displayName = 'Default'; + +Default.propTypes = { + children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired +}; + +export default Default; diff --git a/src/Switch.js b/src/Switch.js new file mode 100644 index 0000000..84446f4 --- /dev/null +++ b/src/Switch.js @@ -0,0 +1,48 @@ +/** + * @file 模拟`switch case`语句 + * @author daxuewen + */ + +import {Children} from 'react'; +import PropTypes from 'prop-types'; +import Case from './Case'; +import Default from './Default'; + +const renderElement = element => (typeof element === 'function' ? element() : element); + +const Switch = ({value, children, equal}) => { + const childrenCount = Children.count(children); + const lastChild = childrenCount === 1 ? children : children[children.length - 1]; + const defaultChild = lastChild.type === Default ? lastChild : null; + + const cases = children.filter(child => child.type === Case); + const matchedCase = cases.find(({props}) => { + if (Array.isArray(props.value)) { + return props.value.some(item => equal(item, value)); + } + + return equal(props.value, value); + }); + + if (matchedCase) { + return renderElement(matchedCase.props.children); + } + + if (defaultChild) { + return renderElement(defaultChild.props.children); + } + + return null; +}; + +Switch.propTypes = { + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]).isRequired, + children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired, + equal: PropTypes.func +}; + +Switch.defaultProps = { + equal: (a, b) => a === b +}; + +export default Switch;