常用基础策略
- 减少 Context 层级嵌套:尽量将 Context 的提供者(Provider)放置在靠近需要消费(Consumer)数据的组件层级,避免过多中间层级传递。因为每经过一层组件传递,都可能引发不必要的重新渲染。例如,原本在顶层应用组件设置 Context,而只有深层某个子组件使用,若中间组件频繁更新,会导致不必要的 Context 重新渲染。可以将 Context 提供者移到靠近使用它的子组件的父组件层级。
- 拆分 Context:如果 Context 包含多个状态或数据,且这些数据变化频率不同,将其拆分为多个 Context。这样当某个 Context 中的数据变化时,只有依赖该 Context 的组件会重新渲染。比如,一个应用中有用户信息和主题设置信息,用户信息变化频繁,主题设置不常变化。可将用户信息和主题设置分别放在不同的 Context 中,这样主题设置变化时,不会影响依赖用户信息 Context 的组件。
- 使用 Memo 包裹消费组件:对于消费 Context 的组件,使用
createMemo
或 memo
包裹,让 Solid.js 可以基于依赖进行细粒度的更新判断。当 Context 数据变化,但组件依赖的部分没有改变时,组件不会重新渲染。
避免不必要渲染示例
- 减少 Context 层级嵌套示例:
import { createContext, createSignal } from 'solid-js';
// 创建 Context
const MyContext = createContext();
// 原本顶层设置 Context
const App = () => {
const [count, setCount] = createSignal(0);
return (
<MyContext.Provider value={count}>
<div>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
<DeepComponent />
</div>
</MyContext.Provider>
);
};
const DeepComponent = () => {
const count = MyContext.useContext();
return <div>Count: {count()}</div>;
};
// 优化后将 Context 提供者下移
const OptimizedApp = () => {
const [count, setCount] = createSignal(0);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
<InnerProvider count={count}>
<DeepComponent />
</InnerProvider>
</div>
);
};
const InnerProvider = ({ count }) => {
return (
<MyContext.Provider value={count}>
<div>
<DeepComponent />
</div>
</MyContext.Provider>
);
};
- 拆分 Context 示例:
import { createContext, createSignal } from'solid-js';
// 创建用户信息 Context
const UserContext = createContext();
// 创建主题设置 Context
const ThemeContext = createContext();
const App = () => {
const [user, setUser] = createSignal({ name: 'John' });
const [theme, setTheme] = createSignal('light');
return (
<UserContext.Provider value={user}>
<ThemeContext.Provider value={theme}>
<div>
<UserComponent />
<ThemeComponent />
</div>
</ThemeContext.Provider>
</UserContext.Provider>
);
};
const UserComponent = () => {
const user = UserContext.useContext();
return <div>User: {user().name}</div>;
};
const ThemeComponent = () => {
const theme = ThemeContext.useContext();
return <div>Theme: {theme()}</div>;
};
- 使用 Memo 包裹消费组件示例:
import { createContext, createSignal, memo } from'solid-js';
const MyContext = createContext();
const App = () => {
const [count, setCount] = createSignal(0);
return (
<MyContext.Provider value={count}>
<div>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
<MemoizedConsumer />
</div>
</MyContext.Provider>
);
};
const MemoizedConsumer = memo(() => {
const count = MyContext.useContext();
return <div>Count (Memoized): {count()}</div>;
});