首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SolidJS上下文提供程序规范

SolidJS上下文提供程序规范
EN

Stack Overflow用户
提问于 2022-11-18 14:51:48
回答 1查看 83关注 0票数 1

我正在学习本教程中的上下文示例,我从该示例中了解到的是使用自定义提供程序:

代码语言:javascript
复制
import { createSignal, createContext, useContext } from "solid-js";

const CounterContext = createContext();

export function CounterProvider(props) {
  const [count, setCount] = createSignal(props.count || 0),
    counter = [
      count,
      {
        increment() {
          setCount((c) => c + 1);
        },
        decrement() {
          setCount((c) => c - 1);
        },
      },
    ];

  return (
    <CounterContext.Provider value={counter}>
      {props.children}
    </CounterContext.Provider>
  );
}

export function useCounter() {
  return useContext(CounterContext);
}

我有三个问题:

  1. 除了上面的示例之外,我找不到任何关于如何定义自定义上下文提供程序的规范,是否有任何标准或规范可遵循?
  2. 在这个例子中,CounterContext和CounterProvider之间的绑定在哪里?在这一行吗?<CounterContext.Provider value={counter}>。再和createSignal一起使用在计数器上?

那么,依赖关系是:createSignal->CounterProvider?

  1. 我在jsx格式中找不到任何关于具有更复杂对象的createContext的上下文示例,只有在打字稿语法中。这是否一个有效的例子呢?
代码语言:javascript
复制
const SomeContext = createContext({
  someProp: "defaultString",
  someAction: function(){
    console.log('something')
  }
});
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-18 16:47:56

没有自定义上下文,因为所有上下文都是自定义的。而且,也没有规范,因为这个想法非常简单。

Context是一种在不遍历组件层次结构的情况下向组件树传递值的方法。基本上,它是一个JavaScript作用域,组件直接从其中获取值,而不是手动将道具传递到组件树。记住,与React不同的是,Solid的组件被编译成JavaScript函数,函数可以从其外部作用域访问值。

Context.Provider封装内部组件,并通过使用常规的JavaScript作用域链提供值。useContext在其外部作用域中查找提供的上下文,如果存在,则获取值(如果没有使用默认值)。在同一上下文的多个提供者的情况下,最内部的一个将如我们所期望的那样使用,因为变量查找从内部范围到最外层的范围。

要了解更多信息,您可以阅读React的上下文文档,坚实地借用来自React的上下文API的想法。

该示例看起来很复杂,因为具有存储在上下文中的方法的对象尝试一个更简单的对象。

代码语言:javascript
复制
import { createContext, useContext } from 'solid-js';
import { render } from 'solid-js/web';

const CounterContex = createContext<number>(0);

const Child = () => {
  const count = useContext(CounterContex);
  return (
    <div>{count}</div>
  );
};

const App = () => {
  return (
    <div>
      <CounterContex.Provider value={10}>
        <Child />
      </CounterContex.Provider>
    </div>
  );
}

render(App, document.querySelector('#app'));

如果不提供值,则将使用默认值:

代码语言:javascript
复制
import { createContext, useContext } from "solid-js";
import { render } from "solid-js/web";

const CounterContex = createContext<number>(0);

const Child = () => {
  const count = useContext(CounterContex);
  return <div>{count}</div>;
};

const App = () => {
  return (
    <div>
      <Child />
    </div>
  );
};

render(App, document.querySelector("#app"));

可以在组件树的不同级别覆盖上下文值:

代码语言:javascript
复制
import { createContext, useContext } from "solid-js";
import { render } from "solid-js/web";

const CounterContex = createContext<number>(0);

const Child = () => {
  const count = useContext(CounterContex);
  return <div>{count}</div>;
};

const App = () => {
  return (
    <div>
      <CounterContex.Provider value={10}>
        <Child />
        <CounterContex.Provider value={20}>
          <Child />
        </CounterContex.Provider>
      </CounterContex.Provider>
    </div>
  );
};

render(App, document.querySelector("#app"));

现在,让我们在上下文中存储一个信号,并在子组件中使用:

代码语言:javascript
复制
import { createContext, useContext, createSignal } from "solid-js";
import { render } from "solid-js/web";

const [count, setCount] = createSignal(0);

const CounterContex = createContext({
  count,
  setCount,
});

const Child = () => {
  const { count, setCount } = useContext(CounterContex);

  return (
    <div onClick={() => setCount(count() + 1)}>
      Click to increment: {count()}
    </div>
  );
};

const App = () => {
  return (
    <div>
      <Child />
    </div>
  );
};

render(App, document.querySelector("#app"));

让我们重构前面的示例。在本文中,我们将使用undefined作为默认值,但稍后使用上下文提供程序从信号中用getter和setter覆盖它:

代码语言:javascript
复制
import { createContext, useContext, createSignal } from "solid-js";
import { render } from "solid-js/web";

const CounterContex = createContext<any>();

const Child = () => {
  const { count, setCount } = useContext(CounterContex);
  return (
    <div onClick={() => setCount(count() + 1)}>Click to increment: {count}</div>
  );
};

const [count, setCount] = createSignal(0);
const App = () => {
  return (
    <div>
      <CounterContex.Provider value={{ count, setCount }}>
        <Child />
      </CounterContex.Provider>
    </div>
  );
};

render(App, document.querySelector("#app"));

现在是实现您发布的示例的时候了。您的组件包装在一个名为CounterProvider的组件中,但我将明确地发布它。您可以随时将逻辑移动到组件中:

代码语言:javascript
复制
import { createContext, useContext, createSignal } from "solid-js";
import { render } from "solid-js/web";

const CounterContex = createContext<any>();

const Child = () => {
  const [count, { increment, decrement }] = useContext(CounterContex);
  return (
    <div>
      <div>{count()}</div>
      <div onClick={() => increment()}>Click to Increment</div>
      <div onClick={() => decrement()}>Click to Decrement</div>
    </div>
  );
};

const [count, setCount] = createSignal(0);

const o = [
  count,
  {
    increment() {
      setCount((c) => c + 1);
    },
    decrement() {
      setCount((c) => c - 1);
    },
  },
];

const App = () => {
  return (
    <div>
      {/* This time we use an array rather than an object as the context value */}
      <CounterContex.Provider value={o}>
        <Child />
      </CounterContex.Provider>
    </div>
  );
};

render(App, document.querySelector("#app"));

现在回答你的问题:

  1. 您可以从https://www.solidjs.com/docs/latest#createcontext中阅读上下文API上的文档。
  2. CounterContext只是一个封装CounterContext.Provider组件以使其更易于使用的组件。它不是API的一部分。
  3. 一旦您掌握了上下文API背后的思想,您将看到类型记录语法与其无关。type Typescript用于注释存储在上下文中的值,以获得类型提示,这就是全部内容。类型对存储的值没有影响。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74491479

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档