更干净的 React 上下文

Posted

技术标签:

【中文标题】更干净的 React 上下文【英文标题】:Cleaner React contexts 【发布时间】:2019-12-08 21:32:36 【问题描述】:

我开始在 React 中使用带有 ContextAPI 的钩子。

这是我的第一个带有钩子的上下文示例:

import React,  createContext, useState  from 'react';

export const DepartureDateContext = createContext();

export const DepartureDateProvider = (props) => 
    const [departureDate, setDepartureDate] = useState(new Date());

    return (
        <DepartureDateContext.Provider
            value=[departureDate, setDepartureDate]
        >
            props.children
        </DepartureDateContext.Provider>
    )

这是第二个例子:

import React,  createContext, useState  from 'react';

export const OriginContext = createContext();

export const OriginProvider = (props) => 
    const [originText, originSearch] = useState('');

    return (
        <OriginContext.Provider
            value=[originText, originSearch]
        >
            props.children
        </OriginContext.Provider>
    )

当我在这些上下文中使用提供者时,就会出现问题。提供者可以堆叠,它开始看起来很难看。像这样:

<OriginProvider>
  <DepartureDateProvider>
    <DestinationProvider>
      <DestinationDateProvider>
        <FlightSearch/>
      </DestinationDateProvider>
    </DestinationProvider>
  </DepartureDateProvider>
</OriginProvider>

既然有可能我会有更多的上下文,这只会比这更丑陋。

我的问题是,有没有办法让这个更漂亮。例如,将所有这些上下文合并到一个上下文中?如果是这样,我将如何传递所有状态及其处理程序,但又要保持其清洁和可读性?

谢谢。

【问题讨论】:

我认为你的上下文方法是错误的。也许你应该使用 REDUX 来做到这一点。来自原始文档:上下文旨在共享可被视为 React 组件树“全局”的数据,例如当前经过身份验证的用户、主题或首选语言。 reactjs.org/docs/context.html#when-to-use-context 我将上下文用于那些因为我需要它们的状态是全局的。 在这种情况下,创建一个可以是 object 的全局上下文并设置属性,如您正在使用的名称 我确定有办法将它们包装到单个提供程序组件中吗?但有趣的问题,我会关注这个帖子 我想知道那个包装的样子。 【参考方案1】:

我找到了一种解决方案,但我不确定这是否适合我的用例。它将清除堆叠的上下文,但我不知道这是否会在未来提供更多的复杂性(取决于我在合并的上下文中有多少个状态)。

这个想法是将所有状态及其处理程序转移到单个上下文中并将它们一起公开。

这是我所说的虚拟示例:

这是具有多个状态的上下文:

import React,  createContext, useState  from 'react';

export const ContextSample = createContext();

export const ContextSampleProvider = (props) => 
    const [state1, handler1] = useState('');
    const [state2, handler2] = useState('');

    return(
        <ContextSample.Provider
            value=[
                [state1, handler1],
                [state2, handler2]
            ]
        >
            props.children
        </ContextSample.Provider>
    );

这是 App.js:

import React from 'react';
import  ContextSampleProvider  from './components/Contexts/ContextSample';
import Main from './components/Main/Main';

function App() 
  return (
    <ContextSampleProvider>
      <Main/>
    </ContextSampleProvider>
  );


export default App;

这是主要组件:

import React,  useContext, useEffect  from 'react';
import  ContextSample  from '../Contexts/ContextSample';

const Main = () => 
    const [
        [state1, handler1],
        [state2, handler2]
    ] = useContext(ContextSample);

    useEffect(() => 
        handler1('Value1');
        handler2('Value2');
    )

    return(
        <div>
            <div>
                state1
            </div>
            <div>
                state2
            </div>
        </div>
    );


export default Main;

如您所见,我已经删除了嵌套上下文,它看起来更好。

但我担心的是这部分:

const [
        [state1, handler1],
        [state2, handler2]
    ] = useContext(ContextSample);

它可能有更多的状态和处理程序,可能会变得难以阅读。 但是最大的飞跃已经是我不需要首先嵌套所有上下文。

知道这是否是一个好方法,是否有更好的解决方案?

编辑:我在我的博客上发表了一篇讨论这个问题的帖子。对于任何有兴趣的人,请转到 useContext 部分下的https://blog.ryukote.io/2019/08/15/react-hooks/。

【讨论】:

以上是关于更干净的 React 上下文的主要内容,如果未能解决你的问题,请参考以下文章

七. React的上下文(Context)

React 状态管理:上下文 API 作为全局存储

如何使用 React 的 Context 功能将 HTML5 Canvas 上下文传递给 this.props.children?

React 中的状态管理

PHP CURL api 是不是比使用流进行 HTTP/HTTPS 访问更干净/更快/更好?

React.js生态系统概览 [译]