我试图理解一个示例,该示例在here中使用了带有上下文api的高阶组件。
由于我是反应和函数式编程的新手,所以我不了解这里的实际工作方式。我们正在向函数withUser
发送一个函数,该函数返回另一个接收props
的函数。
function withUser(Component) {
return function ConnectedComponent(props) {
return (
<UserContext.Consumer>
{user => <Component {...props} user={user} />}
</UserContext.Consumer>
);
};
}
因此,当我们创建UserAvatar
时,我们将传递接收props
并返回img
的函数。
const UserAvatar = withUser(({ user, size }) => (
<img
className={`user-avatar ${size || ""}`}
alt="user avatar"
src={user.avatar}
/>
));
因此,基本上之后,我们可以想象UserAvatar
为:
const UserAvatar = props => {
return (
<UserContext.Consumer>
{user => <Component {...props} user={user} />}
</UserContext.Consumer>
);
};
Component
在哪里:
({ user, size }) => (
<img
className={`user-avatar ${size || ""}`}
alt="user avatar"
src={user.avatar}
/>
)
我希望到目前为止是正确的,但是我不明白的是这行:
{user => <Component {...props} user={user} />}
当我们已经拥有props
并将user
传递到UserAvatar
组件时,为什么我们需要将此作为函数而不只是返回组件UserStats
组件?
const UserStats = () => (
<UserContext.Consumer>
{user => (
<div className="user-stats">
<div>
<UserAvatar user={user} />
{user.name}
</div>
<div className="stats">
<div>{user.followers} Followers</div>
<div>Following {user.following}</div>
</div>
</div>
)}
</UserContext.Consumer>
);
答案 0 :(得分:2)
也许最简单的方法是描述一个类似的概念:函数装饰器。
// Start with a function, any function.
let add = (a, b) => a + b;
但是现在我们要为参数添加日志记录并返回:
let addWithLogging = (a, b) => {
console.log("Args are ", a, b);
const result = a + b;
console.log("Result is ", result);
return result;
}
Barf。现在,我们简单的单行函数由于一堆东西而变得复杂,而这些东西完全是两个数字相加的结果。如果我们的大多数功能都很简单,并且我们想向所有功能添加日志记录,那么后端计算就是我们的代码库将增加一倍。双桶。
但是,等等,这是JavaScript,我们具有更高阶的函数,并且可以提取装饰器:
// Here we take a function f and wrap it. We'll return a function that will
// collect the arguments, log them, perform f on them, log the result, and
// then finally return that result to the caller.
const withLogging = f => (...args) => {
console.log("Args are ", ...args);
const result = f(...args);
console.log("Result is ", result);
return result;
};
addWithLogging = withLogging(add);
React对高阶组件使用相同的想法,您的组件需要一些其他功能(经常状态和/或进行AJAX调用)。您不想使所有简单复杂的可测试纯功能组件复杂化,因此可以使用更高阶的组件。与上面的日志装饰器非常相似,示例中的高阶组件将一个组件作为参数,并返回一个匿名的纯功能组件,该组件实际上接收道具并将呈现的组件封装在UserContext组件中。
您可以将UserContext组件作为其他组件返回的JSX的一部分:
const UserAvatar = ({ user, size }) => (
<UserContext.Consumer>
<img
className={`user-avatar ${size || ""}`}
alt="user avatar"
src={user.avatar}
/>
</UserContext.Consumer>
);
但是现在,就像在日志记录示例中一样,您正在需要它的每个组件中重复样板。
关于您所引用的特定行,可以说您不需要那里的函数,因为据我所知,user
在呈现组件时已经在props
中。供参考,这里是compiled JSX。
应该更仔细地阅读代码。
之所以需要一个函数,是因为它是上下文使用者。 user
是通过上下文提供程序注入的,而这样做的唯一方法是为它提供一个将参数传递给的函数。