海星吧的react学习:状态库 hox 的基本使用。

海星吧 2023-3-4 6269

react 有很多种状态库,redux、mobx、recoil 等等,这些无一例外都比较难以使用,

相较于这些状态库,hox.js 就比较简单,并且容易理解。

首先创建一个简单的库。

简单的命名一个文件

/src/hox/counter.hox.ts

import { createStore } from "hox";
import { useState } from "react";

/* 任意一个 custom Hook */
const [useCounterStore, CounterStoreProvider] = createStore(() => {
	const [count, setCount] = useState(0);
	const decrement = () => setCount(count - 1);
	const increment = () => setCount(count + 1);
	return {
		count,
		decrement,
		increment,
	};
});
export  {
	useCounterStore,
	CounterStoreProvider,
};

然后在页面上使用它。

import { useCounterStore , CounterStoreProvider} from "@/hox/counter.hox"

const Child_1 = () => {
	const CounterStore = useCounterStore()
	return (
		<div>
			<p>Child_1</p>
			<button onClick={() => CounterStore.increment()}>increment</button>
		</div>
	);
};
const Child_2 = () => {
	const CounterStore = useCounterStore();
	return (
		<div>
			<p>Child_2 ---</p>
			<p>CounterStore.count:{CounterStore.count}</p>
		</div>
	);
};

function TestHox() {
	return (
		<CounterStoreProvider>
			<Child_1></Child_1>
			<Child_2></Child_2>
		</CounterStoreProvider>
	);
}

export default TestHox;

这样在页面上就有了一个可供使用的状态库了。

hox 的 createStore 它接受一个函数和一个options,返回一个数组,数组的第一位是use***Store,第二位是 ***StoreProvider的组件。

在函数中返回的 state 和 function会被存入 ,在父组件使用 ***StoreProvider 将子组件包裹,就能在子组件中使用使用 use***Store 引用状态数据和函数了。

点击按钮后,绑定的事件会去更新状态,count就增加了。

hox 还有一个全局状态 叫 createGlobalStore,这个东西创建的状态需要被 hox 的 HoxRoot 组件作为 Provider 发放。

在hox文件夹下创建一个 index.hox.ts 和一个 user.hox.ts,并且改一下 counter.hox.ts

counter.hox.ts -->

import { useState } from "react";
const CounterStore = () => {
	const [count, setCount] = useState(0);
	const decrement = () => setCount(count - 1);
	const increment = () => setCount(count + 1);
	return {
		count,
		decrement,
		increment,
	};
}
export {
	CounterStore
}

index.hox.ts -->

import { createGlobalStore } from "hox";
import { CounterStore } from "./counter.hox";
import { UserStore } from "./user.hox";

const [useHoxStore, getHoxStore] = createGlobalStore(() => ({
	useCounterStore: CounterStore(),
	useUserStore: UserStore(),
}));

export { useHoxStore, getHoxStore };

user.hox.ts -->

import { ChangeEvent, useMemo, useState } from "react";
const UserStore = () => {
	const [user, setUser] = useState({
		name: "海星吧",
		age: 24,
	});
	const userName = useMemo(() => user.name, [user.name]);
	const userAge = useMemo(() => user.age, [user.age]);
	function setUserName(name: string) {
		setUser((user) => ({
			...user,
			name: name,
		}));
	}
	function setUserAge(age: number) {
		setUser((user) => ({
			...user,
			age: age,
		}));
	}
    function handleInputUserAge(e: ChangeEvent<HTMLInputElement>) {
		setUserAge(parseInt(e.target.value));
	}
	return {
		user,
		userName,
		userAge,
		setUserName,
		setUserAge,
        handleInputUserAge,
	};
};
export { UserStore };

 

在app组件中使用 HoxRoot 包裹。

import { HoxRoot } from "hox";
import AppRouter from "./router";

function App() {
	return (
		<div className="App">
			<div>APP React</div>
			<HoxRoot>
				<>
					<AppRouter></AppRouter>
				</>
			</HoxRoot>
		</div>
	);
}

export default App;

改变一下 TestHox

import { useHoxStore } from "@/hox/index.hox";

const Child_1 = () => {
	const { useCounterStore } = useHoxStore();
	const CounterStore = useCounterStore;
	return (
		<div>
			<p>Child_1</p>
			<button onClick={() => CounterStore.increment()}>increment</button>
		</div>
	);
};

const Child_2 = () => {
	const { useCounterStore, useUserStore } = useHoxStore();
	const CounterStore = useCounterStore;
	return (
		<div>
			<p>Child_2 ---</p>
			<p>CounterStore.count:{CounterStore.count}</p>
			<p>useUserStore.userAge:{useUserStore.userAge}</p>
			<p>useUserStore.userName:{useUserStore.userName}</p>
			<p>Child_2 ---</p>
		</div>
	);
};
const Child_3 = () => {
	const HoxStore = useHoxStore();
	const { useUserStore } = HoxStore;
	return (
		<div>
			<p>Child_3</p>
			<p>{useUserStore.userAge}</p>
			<p>{useUserStore.userName}</p>
			<input type="number" value={useUserStore.user.age} onChange={useUserStore.handleInputUserAge} />
		</div>
	);
};

function TestHox() {
	return (
		<>
			<Child_1></Child_1>
			<Child_2></Child_2>
			<Child_3></Child_3>
		</>
	);
}

export default TestHox;

上面的代码中我们把 counter.hox.ts 的函数直接返回出去,user.hox.ts同理。

在index.hox.ts 创建一个 createGlobalStore,他接收一个返回函数。

import { createGlobalStore } from "hox";
import { CounterStore } from "./counter.hox";
import { UserStore } from "./user.hox";

const [useHoxStore, getHoxStore] = createGlobalStore(() => ({
	useCounterStore: CounterStore(),
	useUserStore: UserStore(),
}));

export { useHoxStore, getHoxStore };

我将user和counter放进这个返回函数里,将他们合成一个对象返回出去。

然后就能在组件中使用 /src/hox/index.hox.ts 返回出来的 useHoxStore 取出里面的数据和函数了。

但是能不能直接修改它的值而不使用hox返回的修改函数呢?

我把 Child__2和3 改一下。

const Child_2 = () => {
	const { useCounterStore, useUserStore } = useHoxStore();
	// const { useCounterStore, useUserStore } = useHoxStore();
	const CounterStore = useCounterStore;
	useEffect(() => console.log("Child_2", useUserStore.user), [useUserStore.user.name]);
	return (
		<div>
			<p>Child_2 ---</p>
			<p>CounterStore.count:{CounterStore.count}</p>
			<p>useUserStore.userAge:{useUserStore.userAge}</p>
			<p>useUserStore.userName:{useUserStore.userName}</p>
			<p>Child_2 ---</p>
		</div>
	);
};
const Child_3 = () => {
	const HoxStore = useHoxStore();
	const { useUserStore } = HoxStore;
	const handleUserName = () => {
		useUserStore.user.name = "海星吧帅的一批";
		console.log(useUserStore.user);
	};
	useEffect(() => console.log("Child_3", useUserStore.user), [useUserStore.user.name]);

	return (
		<div>
			<p>Child_3</p>
			<p>{useUserStore.userAge}</p>
			<p>{useUserStore.userName}</p>
			<input type="number" value={useUserStore.user.age} onChange={useUserStore.handleInputUserAge} />
			<br />
			<button onClick={handleUserName}>海星吧帅的一批</button>
		</div>
	);
};

上面我用 useEffect 跟踪 user.name 数据的更改。

现在有一个函数,他告诉你们我帅的一批,然后点击看看。

NoNoNo,虽然这个数据更改了,但是有这么一个问题,

那就是Child__3组件内把数据改了,但是并没有更新视图。

但是我触发age的更改时会发生什么。

好家伙,这回它又把之前更新的数据返回出去了。

现在页面上就显示我帅的一批,并且年龄是25,但这是不应该的。

所以别把状态内的数据直接更改比较好,引发这样的问题会很难搞。


非常好,你看到这里说明你应该学会了基础的使用了,还不会就去敲代码。

react 使用 hox 来进行状态更新是非常方便的,只不过 hox.js 还是太轻量了。

虽然简便,但是能够直接更改状态值还是不妥,应该在编写的时候就报错还是比较好。

当然,这个库的 createGlobalStore 返回的第二个值是什么意思我还是没搞懂,

我写在组件内一直编译警告,还有一个 withStore 说是让类组件也能用,因为 hox 目前是用在函数式组件里的。

createStore 配置项里的 memo,没想出怎么个使用场景,有想法再更新一下吧。

补充一下,编写代码时请注意,我用的是 hox.js 的 2.1.0 版本,
如果你在网上找到的教程和我不一样,那么请点击这里了查看hox官网的版本迁移
 
弱鸡程序员年底还在加班
最新回复 (2)
  • 海星吧 2023-3-5
    0 2
    平均体 undefined像是我在信息课上没有听课的东西
    弱鸡程序员年底还在加班
  • 海星吧 2023-3-15
    0 3
    欧派兽 奖励三级精华
    感谢感谢
    弱鸡程序员年底还在加班
    • ACG里世界
      4
          
返回
发新帖