Props在React函数组件的传递

最近在使用 React 进行开发时，发现了一个容易被忽视的细节，特此分享。

在使用函数组件时，我们通常会定义一些 props，但要注意在传参的时候存在一些潜在的问题。

例子

让我们来看一个函数组件：

Copy
const OneSearch = (query, engine) => {
...
}

export default OneSearch;

在引用这个组件时，可能会这样写：

Copy
<OneSearch query={oneSearchQuery} engine={engine}></OneSearch>

表面上看起来一切正常，但如果仔细观察函数组件的定义，会发现一个小小的细节，就在传参的地方：(query, engine)

实际上，我们希望应该是这样：({ query, engine })

为什么呢？因为在 React 中，组件的参数是作为一个 JavaScript 对象传递的。在定义函数组件时，我们可以将参数写作 (props) 或者其他任何名字，比如 (cop)。而在引用组件时，JSX 会将传递的参数名和值打包成一个 JavaScript 对象，作为实参传递给组件。props 只是一个约定俗称的名字，你可以通过这个名字来访问传递过来的参数。

另一种写法是 ({ query, engine })，此时形参变成了一个对象，而 JavaScript 语法允许你通过这种形式直接访问对象中的属性。

但是，如果你采用 (query, engine) 这种写法，情况就不同了。query 作为第一个形参，实际上接受的是一个 React 打包的对象，长这样：

Copy
{
query: ...,
engine: ...
}

而且！这样子写是不会报错的，因为 JS 里的函数，调用参数无论传够了还是没够，甚至是多了，JavaScript 都不报错。（至少在主流浏览器实现上是这样）

这种逆天写法，换其他语言早就开始叫了，Python 会在运行时爆个 TypeError，编译型语言像 C/C++ 没等你运行编译器就先开始叫唤了，编译都过不去。

但 JavaScript 允许这种行为发生而没有任何提示！你参数传多了，就会按照实参的顺序依次给到形参（如果调用时没有指定哪个实参要给到哪个形参的话），剩下的就不管；你传少了，还是这样。函数里面要是引用没给到实参的形参咋办？那么你引用的那个形参的值就是undefined，没了。就一个undefined，甚至警告都不会有。

总结

因此，在定义 React 组件时，建议采用 (props) 或者 ({ prop1, prop2 }) 的形式，以避免潜在的问题。