用有用的模式重新访问上下文,用SolidJS进行了说明
#javascript #前端 #solidjs

组件是一个函数,取得一些道具并呈现一个视图。在这些道具中,您可能有一些状态元素。当您进行多页水疗中心时,您会在每个新页面上重建组件。您可能需要使用全球商店在它们之间共享状态。对此的有用模式是上下文。您也可以通过参数化函数组件来做到这一点:

(context) => (props) => [HTML like stuff]

您可以沿着道路(例如主题),有用的功能来传递所有可能需要的东西...

有了一些框架,您可以在组件之外声明状态。使用SolidJS,您可以使用createSignal声明状态元素;它可以封装在组件中,也可以在其外部声明。您可以利用此“上下文”:如果您需要在组件之间共享它,则可以在上下文级别上声明。

// context.js

import {createSignal} from from "solid-js";

const [bool, setBool] = createSignal(false);

const context = {
  bool, setBool,
  theme: {...}, 
  ...
}

在下面的示例中,我们从上下文中获得了状态。

const comp1 = (ctx) => {
  const {bool, setBool, theme} = ctx;

  return const Comp1 = (props) =>
     (
        <p>The state value is: {bool() ? "true" : "false"}</p>
        <button onClick={()=> setBool(v => !v}>Toggle</button>
        {props?.children}
    )
}

[...]

import context from "./context";
const Comp1 = comp1(context)
<Comp1>Hi</Comp1>

导航到另一个组件时,您会导入状态并每次导航回到此组件时具有反应性值。

const comp2 = (ctx) => {
  const {bool} = ctx;

  return () =>
     (
      <div>
        <p>Comp1 changed the state: {bool()}</p>
     </div>
    )
}

[...]

import context from "./context";
const Comp2 = comp2(context)
<Comp2/>

我们可以具有从组件中设置数据的异步函数,我们希望在其他地方使用结果。当您想使用SOLIDJS运行异步调用时,在SolidJS文档中指定了应该使用createResource。然后,如果需要更新状态,则应避免使用createEffect,因为这用于突变DOM,而是将then(..)附加到异步调用。让我们来做。

我们模拟异步调用并通过结果更新状态。此外,由于我们可能想从组件的范围中写出此功能,因此我们将其与上下文进行参数化,以便状态设置器可用:

// asyncFunc.js

const asyncFunc = ({setData}) => 
  async (x) =>
    new Promise((resolve, reject) => {
      return setTimeout(() => resolve(x), 1000);
    })
    .then(setData)

我们首先在上下文中添加信号以在组件中共享数据:

// context.js

import {createSignal} from from "solid-js";

const [data, setData] = createSignal("");

const context = {
  data, setData,
  ...
}

在solidjs中使用createRessource处理异步调用:它可以进行论证并返回getter函数(以(argOfFun, Fun)的形式编写)。

import { createEffect, createResource } from "solid-js";
import context from "./context";
import asyncFunc from "./asyncFunc";


const comp3 = (ctx) => {
  // import the state
  const {data, setData, theme} = ctx;
  const AsyncFun = asyncFunction(ctx)

  return function Comp1(props) {
    // run the async function; it will update the state
    const [result] = createResource(100, AsyncFun);

    return(
      <p> Async render: {result()}</p>
    )
  }
}

您可以通过以上导入状态data在其他地方使用它,当您导航时,组件将是最新的。

请注意,函数组件只能运行 ,因此,异步函数将仅运行 。。

如果我们想更改它怎么办?让我们举个例子。我们使用滑块来更改异步函数的参数。

我们使用本地状态来跟踪显示值;这意味着每次渲染组件时都会重置。如果需要持久性,可以选择全球状态。

我们需要实现2个异步调用:第一个调用将在组件渲染时运行,而第二个将在组件终生期间的更改中做出反应。 SolidJS使这简单起来,因为我们可以放心该功能组件仅运行一次。

import ...

const comp4 = (ctx) => {
  // import the state from context
  const {data, setData} = ctx;
  const AsyncFun = asyncFunction(ctx)

  return ()=> {
    // local state to display the slider values, reset on every mount
    const [slide, setSlide] = createSignal(10);

    // initial async call that updates the "data" state
    const [initial] = createResource(slide(), AsyncFun);

    return (
      <div>
        <input
          type="range"
          min="10"
          max="100"
          value="10"
          onchange={({target: {value}) => {
            setSlide(value);
            // dynamic async call
            createResource(value, AsyncFun)
          }}
        />
        <p>{slide()}</p>
        <p>First async render: {initial()}</p>
        <p> Dynamic async update: {data()}.</p>
    </div>
  )

任何其他组件都可以访问反应性状态data

https://codesandbox.io/p/sandbox/github/ndrean/demo-ctx-solid/tree/main?file=%2Fsrc%2Fcontext.js%3A1%2C1