我正在使用新的React Context API而非Redux开发一个新应用,并且在使用之前,例如Redux,当我需要获取用户列表时,我只是调用componentDidMount我的操作,但是现在使用React Context,我的操作可以在内部进行。我的使用者位于我的渲染函数中,这意味着每次调用我的渲染函数时,它将调用我的操作以获取用户列表,这不好,因为我将执行许多不必要的请求。
Redux
componentDidMount
那么,我怎么只能一次调用动作,例如in componentDidMount而不是调用render?
只是为了举例说明,请看下面的代码:
假设我将所有内容包装Providers在一个组件中,如下所示:
Providers
import React from 'react'; import UserProvider from './UserProvider'; import PostProvider from './PostProvider'; export default class Provider extends React.Component { render(){ return( <UserProvider> <PostProvider> {this.props.children} </PostProvider> </UserProvider> ) } }
然后,我将这个Provider组件包装了所有应用程序,如下所示:
import React from 'react'; import Provider from './providers/Provider'; import { Router } from './Router'; export default class App extends React.Component { render() { const Component = Router(); return( <Provider> <Component /> </Provider> ) } }
现在,以我的用户视图为例,它将是这样的:
import React from 'react'; import UserContext from '../contexts/UserContext'; export default class Users extends React.Component { render(){ return( <UserContext.Consumer> {({getUsers, users}) => { getUsers(); return( <h1>Users</h1> <ul> {users.map(user) => ( <li>{user.name}</li> )} </ul> ) }} </UserContext.Consumer> ) } }
我想要的是:
import React from 'react'; import UserContext from '../contexts/UserContext'; export default class Users extends React.Component { componentDidMount(){ this.props.getUsers(); } render(){ return( <UserContext.Consumer> {({users}) => { getUsers(); return( <h1>Users</h1> <ul> {users.map(user) => ( <li>{user.name}</li> )} </ul> ) }} </UserContext.Consumer> ) } }
但是,当然上面的示例不起作用,因为getUsers不存在于我的用户视图中的道具。如果可能的话,正确的方法是什么?
getUsers
编辑: 随着 v16.8.0中 引入react-hooks ,您可以通过使用useContext钩子在功能组件中使用上下文
useContext
const Users = () => { const contextValue = useContext(UserContext); // rest logic here }
编辑: 从版本 16.6.0 起。您可以通过使用上下文的生命周期的方法this.context一样
this.context
class Users extends React.Component { componentDidMount() { let value = this.context; /* perform a side-effect at mount using the value of UserContext */ } componentDidUpdate() { let value = this.context; /* ... */ } componentWillUnmount() { let value = this.context; /* ... */ } render() { let value = this.context; /* render something based on the value of UserContext */ } } Users.contextType = UserContext; // This part is important to access context values
在版本16.6.0之前,您可以按以下方式进行操作
为了在您的生命周期方法中使用Context,您可以将组件编写为
class Users extends React.Component { componentDidMount(){ this.props.getUsers(); } render(){ const { users } = this.props; return( <h1>Users</h1> <ul> {users.map(user) => ( <li>{user.name}</li> )} </ul> ) } } export default props => ( <UserContext.Consumer> {({users, getUsers}) => { return <Users {...props} users={users} getUsers={getUsers} /> }} </UserContext.Consumer> )
通常,您将在您的应用程序中维护一个上下文,将上述登录名打包在HOC中以便重新使用是有意义的。你可以这样写
import UserContext from 'path/to/UserContext'; const withUserContext = Component => { return props => { return ( <UserContext.Consumer> {({users, getUsers}) => { return <Component {...props} users={users} getUsers={getUsers} />; }} </UserContext.Consumer> ); }; };
然后你可以像这样使用它
export default withUserContext(User);