这是我第一次从David Khourshid在React Rally 2017Infinitely Better UIs with Finite Automata的演讲中听到的一句话:"Make impossible states impossible"(顺便说一句,xstate非常棒,David也是)。在谷歌上搜索一下,这似乎是榆树社区的一个相当流行的短语,虽然我不确定谁先说的。
为了说明这意味着什么,让我们看看一个非常简单的例子:
Just FYI
It worked!
Head's up
Watch out!

你可能已经使用或编写了一个具有这种API的组件。这很好,也很干净(如果你不熟悉,在JJSX中,像这样的非赋值道具就相当于把它赋值为 "true",所以success ,就相当于success={true} )。
这就是这种API的失败之处。我应该用这个来渲染什么?
It worked!
它应该混合这些颜色吗?我应该选择一种吗?我应该选择哪个?或者我们应该对试图这样做的开发者大喊大叫,因为他们显然不知道自己在做什么? 提示:最后一个问题不是你应该做的)。
使不可能的状态成为不可能的想法基本上意味着像这样的情况和问题不应该出现。这意味着你设计的API要对组件的可能状态进行明确的区分。这使得组件更容易维护和使用。
那么,我们在这个简单的例子中是怎么做的呢?呼,这些不同的道具所代表的是应该被呈现的警报类型。那么,如果我们不是简单地接受道具本身,而是接受一个type 的道具呢?
Just FYI
It worked!
Head's up
Watch out!
现在不可能有比一个更多的状态了,因为type 这个道具只有三个有效的值(好吧,如果你算上undefined ,就是四个)!这更容易维护,更容易解释/理解,也更难搞乱。每个人都是赢家。
有各种方法可以有效地做到这一点,将布尔值转换为枚举只是其中的一种机制。它可以而且确实变得更加复杂,但这个概念可以严重简化你的组件和应用程序的状态。这就是为什么我建议你看一下David的演讲(这里又是)。也给xstate看一下。那里面有一些很好的想法!祝您好运
P.S. 在发表这篇文章后,有几个人注意到这句话是Richard Feldman在榆树会议上的一个演讲的题目。还有一个来自ReasonML慕尼黑聚会的Patrick Stapfer的演讲。你可能还有兴趣看看@stereobooster的类似博文。
P.S.P.S. 进一步揭示了类似短语的来源。
下面是我在babel7博文中的部分内容,虽然没有进入最后的剪辑,但我想你会喜欢。
这是一个非常简单的例子,它是一个自定义宏,将line和column 的导入与代码中出现的行或列进行交换。
// line-column.macro
module.exports = createMacro(lineColumnMacro)
function lineColumnMacro({references, babel}) {
references.line.forEach(referencePath => {
const num = referencePath.node.loc.start.line
referencePath.replaceWith(babel.types.numberLiteral(num))
})
references.column.forEach(referencePath => {
const num = referencePath.node.loc.start.column
referencePath.replaceWith(babel.types.numberLiteral(num))
})
}
然后是这段代码:
`import {line, column} from './line-column.macro'
`
``console.log(`we're at ${line}:${column}`)
console.log(`and now we're at ${line}:${column}`)``
这将被转译成:
console.log(`we're at ${3}:${32}`)
console.log(`and now we're at ${4}:${40}`)
而且我们不需要改变任何配置来添加这个自定义转换。用这种方式编写和使用代码转换是相当容易的。你不能做一个完整的babel插件所能做的一切,但我们只是刚刚开始,并期待着社区对这一能力的发挥。
在astexplorer.net上玩玩上述宏的例子。看看你能不能让它支持一个叫做lineColumn 的导入,这个导入被替换成行和列的总和。只是为了好玩