npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

xlstate

v0.0.8

Published

React state management libraries

Downloads

3

Readme

xlstate

参考:unstated-next

与 unstated-next 区别

  • unstated-next 是基于 useContext + useState 开发;xlstate 是通过 useContext + useReducer;
  • unstated-next 输出两个 api:createContainer 和 useContainer;xlstate 输出一个 api:createContainer;

安装

npm install --save xlstate

Example

// state - 创建 state 和 reducer
import { createContainer } from "xlstate"
const STATES = {
  info: {
    name: "Jack",
    age: 16,
  },
}

const REDUCERS = {
  setInfo(state, { payload }) {
    return {
      ...state,
      info: {
        ...payload,
      },
    }
  },
}
// 建议在状态初始化时调用 createContainer 方法,将 Provider 和 useGloContext 输出
const { Provider, useGloContext } = createContainer(STATES, REDUCERS)

export { Provider, useGloContext }
// 使用
import React from "react"
import { render } from "react-dom"
import { Provider, useGloContext } from "./state"

// 在自组件中调用  useGloContext 方法获取全局 context 值
function UserInfo() {
  const { info, dispatch, name } = useGloContext()
  console.log(name)
  return (
    <div>
      <button
        onClick={() => {
          dispatch({
            type: "setInfo",
            payload: {
              name: "Jxl",
              age: 20,
            },
          })
        }}
      >
        change info
      </button>
      <p>{name}</p>
      <p>{info.age}</p>
    </div>
  )
}

// 用 Provider 在 最外层将组件包裹
function App() {
  const name = "jxl"
  return (
    <Provider globalVal={{ name }}>
      <UserInfo />
    </Provider>
  )
}

render(<App />, document.getElementById("root"))

其他奇技用法

1、多 Provider 嵌套

  • 创建两个 reducer
// models/store.js
import { createContainer } from "xlstate"
const STATES = {
  age: 16,
}

const REDUCERS = {
  setAge(state, { payload }) {
    return {
      ...state,
      age: payload,
    }
  },
}

const Store = createContainer(STATES, REDUCERS)

export default Store

// models/reducer.js
import { createContainer } from "xlstate"
const STATES = {
  name: "Leon",
}

const REDUCERS = {
  setName(state, { payload }) {
    return {
      ...state,
      name: payload,
    }
  },
}

const Reducer = createContainer(STATES, REDUCERS)

export default Reducer
  • 在入口引入
// index.js
import React from "react"
import { render } from "react-dom"

import Store from "./models/store"
import Reducer from "./models/reducer"

import PageOne from "./pages/PageOne"
import PageTwo from "./pages/PageTwo"

function App() {
  const name = "jxl"
  const age = 18

  return (
    <>
      <Reducer.Provider globalVal={{ age }}>
        <PageOne />
      </Reducer.Provider>
      <Store.Provider globalVal={{ name }}>
        <PageTwo />
      </Store.Provider>
    </>
  )
}

分别用不同的 Provider 嵌套子组件。

  • 在子组件中使用
// PageOne.js
import React from "react"
import Reducer from "../models/reducer"

export default () => {
  const global = Reducer.useGloContext()
  console.log("PageOne: ", global)

  return <div>page one</div>
}

// PageTwo.js
import React from "react"
import Store from "../models/store"

export default () => {
  const global = Store.useGloContext()
  console.log("PageTwo: ", global)

  return <div>page two</div>
}

在子组件内可获取到对应的 state。

2、多 Provider + 嵌套

在上面基础上,增加 PageThree 组件;

  • 修改入口

PageThree 外层嵌套了 Store.Provider

// index.js
import PageOne from "./pages/PageOne"
import PageTwo from "./pages/PageTwo"
import PageThree from "./pages/PageThree"

function App() {
  const name = "jxl"
  const age = 18

  return (
    <>
      <Reducer.Provider globalVal={{ age }}>
        <PageOne />

        <Store.Provider>
          <PageThree />
        </Store.Provider>
      </Reducer.Provider>

      <Store.Provider globalVal={{ name }}>
        <PageTwo />
      </Store.Provider>
    </>
  )
}

如果 StoreglobalVal 都有 age 属性,则默认 globalVal 会覆盖掉 store 的。

// globalVal 会覆盖掉 store 的
<Store.Provider globalVal={{ age }}>
  <PageThree />
</Store.Provider>
  • PageThree 组件使用
// PageThree.js
import React from "react"

import Store from "../models/store"
import Reducer from "../models/reducer"

export default () => {
  const storeState = Store.useGloContext()
  const reducerState = Reducer.useGloContext()
  console.log("PageThreeStoreState: ", storeState)
  console.log("PageThreeReducerState: ", reducerState)

  return <div>page three</div>
}

PageThree 组件用 Store.Provider 包裹,父级又用 Reducer.Provider 包裹,在 PageThree 组件内部,可用不同的 reducer 获取对应的 state 状态。

  • 修改 state
// PageThree.js
import React from "react"

import Store from "../models/store"
import Reducer from "../models/reducer"

export default () => {
  const storeState = Store.useGloContext()
  const reducerState = Reducer.useGloContext()
  console.log("PageThreeStoreState: ", storeState)
  console.log("PageThreeReducerState: ", reducerState)

  const { dispatch } = storeState

  return (
    <>
      <div>page three</div>
      <button
        onClick={() => {
          dispatch({
            type: "setAge",
            payload: 100,
          })
        }}
      >
        改状态
      </button>
    </>
  )
}

3、同 Provider + 嵌套

再创建 PageFour 组件

  • 入口添加

PageFour 外层嵌套了 Store.Provider,并添加 globalVal

// index.js
import PageOne from "./pages/PageOne"
import PageTwo from "./pages/PageTwo"
import PageThree from "./pages/PageThree"

function App() {
  const name = "jxl"
  const age = 18

  return (
    <>
      <Reducer.Provider globalVal={{ age }}>
        <PageOne />

        <Store.Provider>
          <PageThree />
        </Store.Provider>
      </Reducer.Provider>

      <Store.Provider globalVal={{ name }}>
        <PageTwo />

        <Store.Provider globalVal={{ age }}>
          <PageFour />
        </Store.Provider>
      </Store.Provider>
    </>
  )
}
  • PageFour 中使用

PageFour 外嵌套了 Store.Provider,外层又嵌套了 Store.Provider,但是在 PageFour 获取的是最靠近的状态。

import React from "react"
import Store from "../models/store"

export default () => {
  const global = Store.useGloContext()
  console.log("PageFour: ", global)

  return <div>page one</div>
}

总结

  • xlstate 可创建多个 reducer,也可嵌套多层 Provider
  • globalVal 的值和 reducer 状态值相同时,globalVal 会覆盖 reducer 的
  • 组件嵌套不同 Provider 时,可使用对应的 reducer 方法去获取状态
  • 组件嵌套相同 Provider 时,组件内部获取的状态以最近嵌套的 Provider 为主