在React中,所有道具都会自动更新并传播给孩子,这很好,但是速度慢了,并且需要在某个时候进行大量的优化。
因此,我正在用SolidJS构建一个使用Context + createStore模式的应用程序,并且在使用该状态时遇到了问题。
我想要创建AppProvider组件来管理State道具和Dispatch函数。提供者将在appStore上执行所有操作,实现函数,并通过AppContextState和AppContextDispatch提供程序为它们提供服务。
然后,我需要使用这些数据来更新依赖于它的组件。
请看下面的代码:
/// index.tsx
import { render } from 'solid-js/web';
import { AppProvider } from '@/providers/AppProvider';
import App from './App';
render(() => (
<AppProvider>
<App />
</AppProvider>
), document.getElementById('root') as HTMLElement);/// AppProvider.tsx
import { createContext, useContext, JSX } from 'solid-js';
import { createStore } from 'solid-js/store';
// Interfaces
interface IAppState {
isConnected: boolean;
user: { name: string; }
}
interface IAppDispatch {
connect: () => Promise<void>;
disconnect: () => Promise<void>;
}
// Initialize
const initialState = {
isConnected: false,
user: { name: '' }
}
const initialDispatch = {
connect: () => {},
disconnect: () => {}
}
// Contexts
const AppContextState = createContext<IAppState>();
const AppContextDispatch = createContext<IAppDispatch>();
export const useAppState = () => useContext(AppContextState);
export const useAppDispatch = () => useContext(AppContextDispatch);
// Provider
export const AppProvider = (props: { children: JSX.Element }) => {
const [appStore, setAppStore] = createStore<IAppState>(initialState);
async function connect() {
setAppStore("isConnected", true);
setAppStore("user", "name", 'Chad');
}
async function disconnect() {
setAppStore("isConnected", false);
setAppStore("user", "name", '');
}
return (
<AppContextState.Provider value={appStore}>
<AppContextDispatch.Provider value={{ connect, disconnect }}>
{props.children}
</AppContextDispatch.Provider>
</AppContextState.Provider>
)
}/// App.tsx
import { useAppState, useAppDispatch } from '@/providers/AppProvider';
export default function App() {
const { user, isConnected } = useAppState();
const { connect, disconnect } = useAppDispatch();
return (
<Show when={isConnected} fallback={<button onClick={connect}>Connect</button>}>
<button onClick={disconnect}>Disconnect</button>
<h3>Your Name: {user.name}</h3>
</Show>
)
}这个组件将显示一个button,它应该运行connect函数并更新isConnected状态,并使<Show>块中的组件可见,但它什么也不做。
我验证了在connect方法中通过记录appStore的数据来更新状态。
当我将组件更改为依赖于user.name而不是isConnected时,它可以工作。
<Show when={user.name} fallback={<button onClick={connect}>Connect</button>}>
<button onClick={disconnect}>Disconnect</button>
<h3>Your Name: {user.name}</h3>
</Show>不过,我的应用程序有许多组件,取决于不同的数据类型,包括boolean,在本例中,有些组件在SolidJS中不起作用。
我想知道我在这里做错了什么,并且理解在组件之间共享状态的最佳方式是什么。我一直在阅读文档并摆弄它,但这个特殊的问题困扰了我几天。
发布于 2022-09-09 03:01:01
无法跟踪实心中的普通值。
这里的问题是,原始值/变量在实体中不能是反应性的。我们有两种跟踪值访问的方法:通过函数调用和通过属性getter/代理(它们使用遮罩下的信号)。
那么,当您访问商店属性时会发生什么呢?
const state = useAppState();
createEffect(() => {
console.log(state.isConnected)
})在这种情况下,属性访问是在效果内进行的,因此,当属性值更新时,它会被跟踪并重新运行。另一方面,在这方面:
const { isConnected } = useAppState();我们在组件的顶层访问属性(它是untrack编辑的,而不是实体中的反应性)。因此,即使我们在一个具有反应性的上下文中使用这个值(比如when螺旋桨),我们也不能运行任何特殊的底层跟踪来设置更新。
那么,为什么user.name起作用呢?
原因是存储是深度反应的(对于原语、对象和数组),所以
const { user } = useAppState();这意味着您正在急切地访问用户对象(因此,如果用户属性更改,您将不会得到更新),但是用户对象的属性尚未被访问,它们只能在<Show when={user.name}>中被进一步访问,因此可以跟踪属性访问user.name。
https://stackoverflow.com/questions/73578823
复制相似问题