ರಿಯಾಕ್ಟ್ ಕಾಂಟೆಕ್ಸ್ಟ್ API-ಗಾಗಿ ಸುಧಾರಿತ ಪ್ಯಾಟರ್ನ್ಗಳನ್ನು ಅನ್ವೇಷಿಸಿ, ಇದರಲ್ಲಿ ಕಾಂಪೌಂಡ್ ಕಾಂಪೊನೆಂಟ್ಸ್, ಡೈನಾಮಿಕ್ ಕಾಂಟೆಕ್ಸ್ಟ್ಸ್, ಮತ್ತು ಸಂಕೀರ್ಣ ಸ್ಟೇಟ್ ಮ್ಯಾನೇಜ್ಮೆಂಟ್ಗಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಿದ ಕಾರ್ಯಕ್ಷಮತೆಯ ತಂತ್ರಗಳು ಸೇರಿವೆ.
ಸ್ಟೇಟ್ ಮ್ಯಾನೇಜ್ಮೆಂಟ್ಗಾಗಿ ಸುಧಾರಿತ ರಿಯಾಕ್ಟ್ ಕಾಂಟೆಕ್ಸ್ಟ್ API ಪ್ಯಾಟರ್ನ್ಗಳು
ರಿಯಾಕ್ಟ್ ಕಾಂಟೆಕ್ಸ್ಟ್ APIಯು ಪ್ರಾಪ್ ಡ್ರಿಲ್ಲಿಂಗ್ ಇಲ್ಲದೆ ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ನಾದ್ಯಂತ ಸ್ಟೇಟ್ ಹಂಚಿಕೊಳ್ಳಲು ಒಂದು ಶಕ್ತಿಯುತ ವ್ಯವಸ್ಥೆಯನ್ನು ಒದಗಿಸುತ್ತದೆ. ಇದರ ಮೂಲಭೂತ ಬಳಕೆ ಸರಳವಾಗಿದ್ದರೂ, ಅದರ ಸಂಪೂರ್ಣ ಸಾಮರ್ಥ್ಯವನ್ನು ಬಳಸಿಕೊಳ್ಳಲು ಸಂಕೀರ್ಣ ಸ್ಟೇಟ್ ಮ್ಯಾನೇಜ್ಮೆಂಟ್ ಸನ್ನಿವೇಶಗಳನ್ನು ನಿಭಾಯಿಸಬಲ್ಲ ಸುಧಾರಿತ ಪ್ಯಾಟರ್ನ್ಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವ ಅಗತ್ಯವಿದೆ. ಈ ಲೇಖನವು ಇಂತಹ ಹಲವಾರು ಪ್ಯಾಟರ್ನ್ಗಳನ್ನು ಅನ್ವೇಷಿಸುತ್ತದೆ, ಪ್ರಾಯೋಗಿಕ ಉದಾಹರಣೆಗಳು ಮತ್ತು ನಿಮ್ಮ ರಿಯಾಕ್ಟ್ ಅಭಿವೃದ್ಧಿಯನ್ನು ಉನ್ನತೀಕರಿಸಲು ಕ್ರಿಯಾತ್ಮಕ ಒಳನೋಟಗಳನ್ನು ನೀಡುತ್ತದೆ.
ಮೂಲಭೂತ ಕಾಂಟೆಕ್ಸ್ಟ್ APIಯ ಮಿತಿಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು
ಸುಧಾರಿತ ಪ್ಯಾಟರ್ನ್ಗಳಿಗೆ ಹೋಗುವ ಮೊದಲು, ಮೂಲಭೂತ ಕಾಂಟೆಕ್ಸ್ಟ್ APIಯ ಮಿತಿಗಳನ್ನು ಒಪ್ಪಿಕೊಳ್ಳುವುದು ಬಹಳ ಮುಖ್ಯ. ಸರಳ, ಜಾಗತಿಕವಾಗಿ ಲಭ್ಯವಿರುವ ಸ್ಟೇಟ್ಗೆ ಇದು ಸೂಕ್ತವಾಗಿದ್ದರೂ, ಆಗಾಗ್ಗೆ ಬದಲಾಗುವ ಸ್ಟೇಟ್ ಹೊಂದಿರುವ ಸಂಕೀರ್ಣ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ ಇದು ಅನಾನುಕೂಲ ಮತ್ತು ಅಸಮರ್ಥವಾಗಬಹುದು. ಕಾಂಟೆಕ್ಸ್ಟ್ ಮೌಲ್ಯವು ಬದಲಾದಾಗಲೆಲ್ಲಾ, ಕಾಂಟೆಕ್ಸ್ಟ್ ಬಳಸುವ ಪ್ರತಿಯೊಂದು ಕಾಂಪೊನೆಂಟ್ ಕೂಡ ಮರು-ರೆಂಡರ್ ಆಗುತ್ತದೆ, ಆ ಕಾಂಪೊನೆಂಟ್ ಬದಲಾದ ಸ್ಟೇಟ್ನ ನಿರ್ದಿಷ್ಟ ಭಾಗವನ್ನು ಅವಲಂಬಿಸದಿದ್ದರೂ ಸಹ. ಇದು ಕಾರ್ಯಕ್ಷಮತೆಯ ಅಡಚಣೆಗಳಿಗೆ ಕಾರಣವಾಗಬಹುದು.
ಪ್ಯಾಟರ್ನ್ 1: ಕಾಂಟೆಕ್ಸ್ಟ್ನೊಂದಿಗೆ ಕಾಂಪೌಂಡ್ ಕಾಂಪೊನೆಂಟ್ಸ್
ಕಾಂಪೌಂಡ್ ಕಾಂಪೊನೆಂಟ್ ಪ್ಯಾಟರ್ನ್, ಕಾಂಟೆಕ್ಸ್ಟ್ ಮೂಲಕ ಅಂತರ್ಗತವಾಗಿ ಸ್ಟೇಟ್ ಮತ್ತು ಲಾಜಿಕ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳುವ ಸಂಬಂಧಿತ ಕಾಂಪೊನೆಂಟ್ಗಳ ಗುಂಪನ್ನು ರಚಿಸುವ ಮೂಲಕ ಕಾಂಟೆಕ್ಸ್ಟ್ API ಅನ್ನು ವರ್ಧಿಸುತ್ತದೆ. ಈ ಪ್ಯಾಟರ್ನ್ ಮರುಬಳಕೆಯನ್ನು ಉತ್ತೇಜಿಸುತ್ತದೆ ಮತ್ತು ಗ್ರಾಹಕರಿಗೆ API ಅನ್ನು ಸರಳಗೊಳಿಸುತ್ತದೆ. ಇದು ಸಂಕೀರ್ಣ ಲಾಜಿಕ್ ಅನ್ನು ಸರಳ ಅನುಷ್ಠಾನದೊಂದಿಗೆ ಸಂಕ್ಷೇಪಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ.
ಉದಾಹರಣೆ: ಒಂದು ಟ್ಯಾಬ್ ಕಾಂಪೊನೆಂಟ್
ಇದನ್ನು ಒಂದು ಟ್ಯಾಬ್ ಕಾಂಪೊನೆಂಟ್ ಮೂಲಕ ವಿವರಿಸೋಣ. ಅನೇಕ ಲೇಯರ್ಗಳ ಮೂಲಕ ಪ್ರಾಪ್ಸ್ ಅನ್ನು ರವಾನಿಸುವ ಬದಲು, Tab
ಕಾಂಪೊನೆಂಟ್ಗಳು ಹಂಚಿದ ಕಾಂಟೆಕ್ಸ್ಟ್ ಮೂಲಕ ಅಂತರ್ಗತವಾಗಿ ಸಂವಹನ ನಡೆಸುತ್ತವೆ.
// TabContext.js
import React, { createContext, useContext, useState, ReactNode } from 'react';
interface TabContextType {
activeTab: string;
setActiveTab: (tab: string) => void;
}
const TabContext = createContext(undefined);
interface TabProviderProps {
children: ReactNode;
defaultTab: string;
}
export const TabProvider: React.FC = ({ children, defaultTab }) => {
const [activeTab, setActiveTab] = useState(defaultTab);
const value: TabContextType = {
activeTab,
setActiveTab,
};
return {children} ;
};
export const useTabContext = () => {
const context = useContext(TabContext);
if (!context) {
throw new Error('useTabContext must be used within a TabProvider');
}
return context;
};
// TabList.js
import React, { ReactNode } from 'react';
interface TabListProps {
children: ReactNode;
}
export const TabList: React.FC = ({ children }) => {
return {children};
};
// Tab.js
import React, { ReactNode } from 'react';
import { useTabContext } from './TabContext';
interface TabProps {
label: string;
children: ReactNode;
}
export const Tab: React.FC = ({ label, children }) => {
const { activeTab, setActiveTab } = useTabContext();
const isActive = activeTab === label;
const handleClick = () => {
setActiveTab(label);
};
return (
);
};
// TabPanel.js
import React, { ReactNode } from 'react';
import { useTabContext } from './TabContext';
interface TabPanelProps {
label: string;
children: ReactNode;
}
export const TabPanel: React.FC = ({ label, children }) => {
const { activeTab } = useTabContext();
const isActive = activeTab === label;
return (
{isActive && children}
);
};
// Usage
import { TabProvider, TabList, Tab, TabPanel } from './components/Tabs';
function App() {
return (
Tab 1
Tab 2
Tab 3
Content for Tab 1
Content for Tab 2
Content for Tab 3
);
}
export default App;
ಪ್ರಯೋಜನಗಳು:
- ಗ್ರಾಹಕರಿಗೆ ಸರಳೀಕೃತ API: ಬಳಕೆದಾರರು ಕೇವಲ
Tab
,TabList
, ಮತ್ತುTabPanel
ಬಗ್ಗೆ ಮಾತ್ರ ಚಿಂತಿಸಬೇಕಾಗುತ್ತದೆ. - ಅಂತರ್ಗತ ಸ್ಟೇಟ್ ಹಂಚಿಕೆ: ಕಾಂಪೊನೆಂಟ್ಗಳು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಹಂಚಿದ ಸ್ಟೇಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸುತ್ತವೆ ಮತ್ತು ನವೀಕರಿಸುತ್ತವೆ.
- ಸುಧಾರಿತ ಮರುಬಳಕೆ:
Tab
ಕಾಂಪೊನೆಂಟ್ ಅನ್ನು ವಿಭಿನ್ನ ಸಂದರ್ಭಗಳಲ್ಲಿ ಸುಲಭವಾಗಿ ಮರುಬಳಕೆ ಮಾಡಬಹುದು.
ಪ್ಯಾಟರ್ನ್ 2: ಡೈನಾಮಿಕ್ ಕಾಂಟೆಕ್ಸ್ಟ್ಸ್
ಕೆಲವು ಸನ್ನಿವೇಶಗಳಲ್ಲಿ, ಕಾಂಪೊನೆಂಟ್ ಟ್ರೀಯಲ್ಲಿನ ಕಾಂಪೊನೆಂಟ್ನ ಸ್ಥಾನ ಅಥವಾ ಇತರ ಡೈನಾಮಿಕ್ ಅಂಶಗಳ ಆಧಾರದ ಮೇಲೆ ನಿಮಗೆ ವಿಭಿನ್ನ ಕಾಂಟೆಕ್ಸ್ಟ್ ಮೌಲ್ಯಗಳು ಬೇಕಾಗಬಹುದು. ಡೈನಾಮಿಕ್ ಕಾಂಟೆಕ್ಸ್ಟ್ಗಳು ನಿರ್ದಿಷ್ಟ ಪರಿಸ್ಥಿತಿಗಳ ಆಧಾರದ ಮೇಲೆ ಬದಲಾಗುವ ಕಾಂಟೆಕ್ಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ರಚಿಸಲು ಮತ್ತು ಒದಗಿಸಲು ನಿಮಗೆ ಅನುವು ಮಾಡಿಕೊಡುತ್ತವೆ.
ಉದಾಹರಣೆ: ಡೈನಾಮಿಕ್ ಕಾಂಟೆಕ್ಸ್ಟ್ಗಳೊಂದಿಗೆ ಥೀಮಿಂಗ್
ಬಳಕೆದಾರರ ಆದ್ಯತೆಗಳು ಅಥವಾ ಅವರು ಇರುವ ಅಪ್ಲಿಕೇಶನ್ನ ವಿಭಾಗವನ್ನು ಆಧರಿಸಿ ನೀವು ವಿಭಿನ್ನ ಥೀಮ್ಗಳನ್ನು ಒದಗಿಸಲು ಬಯಸುವ ಥೀಮಿಂಗ್ ಸಿಸ್ಟಮ್ ಅನ್ನು ಪರಿಗಣಿಸಿ. ನಾವು ಲೈಟ್ ಮತ್ತು ಡಾರ್ಕ್ ಥೀಮ್ನೊಂದಿಗೆ ಸರಳೀಕೃತ ಉದಾಹರಣೆಯನ್ನು ಮಾಡಬಹುದು.
// ThemeContext.js
import React, { createContext, useContext, useState, ReactNode } from 'react';
interface Theme {
background: string;
color: string;
}
interface ThemeContextType {
theme: Theme;
toggleTheme: () => void;
}
const defaultTheme: Theme = {
background: 'white',
color: 'black'
};
const darkTheme: Theme = {
background: 'black',
color: 'white'
};
const ThemeContext = createContext({
theme: defaultTheme,
toggleTheme: () => {}
});
interface ThemeProviderProps {
children: ReactNode;
}
export const ThemeProvider: React.FC = ({ children }) => {
const [isDarkTheme, setIsDarkTheme] = useState(false);
const theme = isDarkTheme ? darkTheme : defaultTheme;
const toggleTheme = () => {
setIsDarkTheme(!isDarkTheme);
};
const value: ThemeContextType = {
theme,
toggleTheme,
};
return {children} ;
};
export const useTheme = () => {
return useContext(ThemeContext);
};
// Usage
import { useTheme, ThemeProvider } from './ThemeContext';
function MyComponent() {
const { theme, toggleTheme } = useTheme();
return (
This is a themed component.
);
}
function App() {
return (
);
}
export default App;
ಈ ಉದಾಹರಣೆಯಲ್ಲಿ, ThemeProvider
isDarkTheme
ಸ್ಟೇಟ್ ಆಧರಿಸಿ ಥೀಮ್ ಅನ್ನು ಡೈನಾಮಿಕ್ ಆಗಿ ನಿರ್ಧರಿಸುತ್ತದೆ. useTheme
ಹುಕ್ ಬಳಸುವ ಕಾಂಪೊನೆಂಟ್ಗಳು ಥೀಮ್ ಬದಲಾದಾಗ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಮರು-ರೆಂಡರ್ ಆಗುತ್ತವೆ.
ಪ್ಯಾಟರ್ನ್ 3: ಸಂಕೀರ್ಣ ಸ್ಟೇಟ್ಗಾಗಿ useReducer ಜೊತೆ ಕಾಂಟೆಕ್ಸ್ಟ್
ಸಂಕೀರ್ಣ ಸ್ಟೇಟ್ ಲಾಜಿಕ್ ಅನ್ನು ನಿರ್ವಹಿಸಲು, ಕಾಂಟೆಕ್ಸ್ಟ್ API ಅನ್ನು useReducer
ಜೊತೆ ಸಂಯೋಜಿಸುವುದು ಒಂದು ಅತ್ಯುತ್ತಮ ವಿಧಾನವಾಗಿದೆ. useReducer
ಆಕ್ಷನ್ಗಳ ಆಧಾರದ ಮೇಲೆ ಸ್ಟೇಟ್ ಅನ್ನು ನವೀಕರಿಸಲು ಒಂದು ರಚನಾತ್ಮಕ ಮಾರ್ಗವನ್ನು ಒದಗಿಸುತ್ತದೆ, ಮತ್ತು ಕಾಂಟೆಕ್ಸ್ಟ್ API ಈ ಸ್ಟೇಟ್ ಮತ್ತು ಡಿಸ್ಪ್ಯಾಚ್ ಫಂಕ್ಷನ್ ಅನ್ನು ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ನಾದ್ಯಂತ ಹಂಚಿಕೊಳ್ಳಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ.
ಉದಾಹರಣೆ: ಒಂದು ಸರಳ ಟುಡು ಲಿಸ್ಟ್
// TodoContext.js
import React, { createContext, useContext, useReducer, ReactNode } from 'react';
interface Todo {
id: number;
text: string;
completed: boolean;
}
interface TodoState {
todos: Todo[];
}
type TodoAction =
| { type: 'ADD_TODO'; text: string }
| { type: 'TOGGLE_TODO'; id: number }
| { type: 'DELETE_TODO'; id: number };
interface TodoContextType {
state: TodoState;
dispatch: React.Dispatch;
}
const initialState: TodoState = {
todos: [],
};
const todoReducer = (state: TodoState, action: TodoAction): TodoState => {
switch (action.type) {
case 'ADD_TODO':
return {
...state,
todos: [...state.todos, { id: Date.now(), text: action.text, completed: false }],
};
case 'TOGGLE_TODO':
return {
...state,
todos: state.todos.map((todo) =>
todo.id === action.id ? { ...todo, completed: !todo.completed } : todo
),
};
case 'DELETE_TODO':
return {
...state,
todos: state.todos.filter((todo) => todo.id !== action.id),
};
default:
return state;
}
};
const TodoContext = createContext(undefined);
interface TodoProviderProps {
children: ReactNode;
}
export const TodoProvider: React.FC = ({ children }) => {
const [state, dispatch] = useReducer(todoReducer, initialState);
const value: TodoContextType = {
state,
dispatch,
};
return {children} ;
};
export const useTodo = () => {
const context = useContext(TodoContext);
if (!context) {
throw new Error('useTodo must be used within a TodoProvider');
}
return context;
};
// Usage
import { useTodo, TodoProvider } from './TodoContext';
function TodoList() {
const { state, dispatch } = useTodo();
return (
{state.todos.map((todo) => (
-
{todo.text}
))}
);
}
function AddTodo() {
const { dispatch } = useTodo();
const [text, setText] = React.useState('');
const handleSubmit = (e) => {
e.preventDefault();
dispatch({ type: 'ADD_TODO', text });
setText('');
};
return (
);
}
function App() {
return (
);
}
export default App;
ಈ ಪ್ಯಾಟರ್ನ್ ಸ್ಟೇಟ್ ಮ್ಯಾನೇಜ್ಮೆಂಟ್ ಲಾಜಿಕ್ ಅನ್ನು ರಿಡ್ಯೂಸರ್ನೊಳಗೆ ಕೇಂದ್ರೀಕರಿಸುತ್ತದೆ, ಇದು ತರ್ಕಿಸಲು ಮತ್ತು ಪರೀಕ್ಷಿಸಲು ಸುಲಭವಾಗಿಸುತ್ತದೆ. ಕಾಂಪೊನೆಂಟ್ಗಳು ಸ್ಟೇಟ್ ಅನ್ನು ನೇರವಾಗಿ ನಿರ್ವಹಿಸುವ ಅಗತ್ಯವಿಲ್ಲದೆ ಅದನ್ನು ನವೀಕರಿಸಲು ಆಕ್ಷನ್ಗಳನ್ನು ಡಿಸ್ಪ್ಯಾಚ್ ಮಾಡಬಹುದು.
ಪ್ಯಾಟರ್ನ್ 4: `useMemo` ಮತ್ತು `useCallback` ಜೊತೆ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಿದ ಕಾಂಟೆಕ್ಸ್ಟ್ ಅಪ್ಡೇಟ್ಗಳು
ಮೊದಲೇ ಹೇಳಿದಂತೆ, ಕಾಂಟೆಕ್ಸ್ಟ್ API ಯೊಂದಿಗೆ ಪ್ರಮುಖ ಕಾರ್ಯಕ್ಷಮತೆಯ ಪರಿಗಣನೆಯು ಅನಗತ್ಯ ಮರು-ರೆಂಡರ್ಗಳು. useMemo
ಮತ್ತು useCallback
ಬಳಕೆಯು ಕಾಂಟೆಕ್ಸ್ಟ್ ಮೌಲ್ಯದ ಅಗತ್ಯ ಭಾಗಗಳು ಮಾತ್ರ ನವೀಕರಿಸಲ್ಪಡುವುದನ್ನು ಮತ್ತು ಫಂಕ್ಷನ್ ರೆಫರೆನ್ಸ್ಗಳು ಸ್ಥಿರವಾಗಿರುವುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳುವ ಮೂಲಕ ಈ ಮರು-ರೆಂಡರ್ಗಳನ್ನು ತಡೆಯಬಹುದು.
ಉದಾಹರಣೆ: ಥೀಮ್ ಕಾಂಟೆಕ್ಸ್ಟ್ ಅನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡುವುದು
// OptimizedThemeContext.js
import React, { createContext, useContext, useState, useMemo, useCallback, ReactNode } from 'react';
interface Theme {
background: string;
color: string;
}
interface ThemeContextType {
theme: Theme;
toggleTheme: () => void;
}
const defaultTheme: Theme = {
background: 'white',
color: 'black'
};
const darkTheme: Theme = {
background: 'black',
color: 'white'
};
const ThemeContext = createContext({
theme: defaultTheme,
toggleTheme: () => {}
});
interface ThemeProviderProps {
children: ReactNode;
}
export const ThemeProvider: React.FC = ({ children }) => {
const [isDarkTheme, setIsDarkTheme] = useState(false);
const theme = isDarkTheme ? darkTheme : defaultTheme;
const toggleTheme = useCallback(() => {
setIsDarkTheme(!isDarkTheme);
}, [isDarkTheme]);
const value: ThemeContextType = useMemo(() => ({
theme,
toggleTheme,
}), [theme, toggleTheme]);
return {children} ;
};
export const useTheme = () => {
return useContext(ThemeContext);
};
ವಿವರಣೆ:
useCallback
toggleTheme
ಫಂಕ್ಷನ್ ಅನ್ನು ಮೆಮೊರೈಸ್ ಮಾಡುತ್ತದೆ. ಇದುisDarkTheme
ಬದಲಾದಾಗ ಮಾತ್ರ ಫಂಕ್ಷನ್ ರೆಫರೆನ್ಸ್ ಬದಲಾಗುವುದನ್ನು ಖಚಿತಪಡಿಸುತ್ತದೆ, ಕೇವಲtoggleTheme
ಫಂಕ್ಷನ್ ಅನ್ನು ಅವಲಂಬಿಸಿರುವ ಕಾಂಪೊನೆಂಟ್ಗಳ ಅನಗತ್ಯ ಮರು-ರೆಂಡರ್ಗಳನ್ನು ತಡೆಯುತ್ತದೆ.useMemo
ಕಾಂಟೆಕ್ಸ್ಟ್ ಮೌಲ್ಯವನ್ನು ಮೆಮೊರೈಸ್ ಮಾಡುತ್ತದೆ. ಇದುtheme
ಅಥವಾtoggleTheme
ಫಂಕ್ಷನ್ ಬದಲಾದಾಗ ಮಾತ್ರ ಕಾಂಟೆಕ್ಸ್ಟ್ ಮೌಲ್ಯ ಬದಲಾಗುವುದನ್ನು ಖಚಿತಪಡಿಸುತ್ತದೆ, ಇದು ಅನಗತ್ಯ ಮರು-ರೆಂಡರ್ಗಳನ್ನು ಮತ್ತಷ್ಟು ತಡೆಯುತ್ತದೆ.
useCallback
ಇಲ್ಲದೆ, ThemeProvider
ನ ಪ್ರತಿ ರೆಂಡರ್ನಲ್ಲಿ toggleTheme
ಫಂಕ್ಷನ್ ಅನ್ನು ಮರುಸೃಷ್ಟಿಸಲಾಗುತ್ತದೆ, ಇದು value
ಬದಲಾಗಲು ಕಾರಣವಾಗುತ್ತದೆ ಮತ್ತು ಥೀಮ್ ಸ್ವತಃ ಬದಲಾಗದಿದ್ದರೂ ಸಹ, ಯಾವುದೇ ಬಳಸುವ ಕಾಂಪೊನೆಂಟ್ಗಳಲ್ಲಿ ಮರು-ರೆಂಡರ್ಗಳನ್ನು ಪ್ರಚೋದಿಸುತ್ತದೆ. useMemo
ತನ್ನ ಡಿಪೆಂಡೆನ್ಸಿಗಳು (theme
ಅಥವಾ toggleTheme
) ಬದಲಾದಾಗ ಮಾತ್ರ ಹೊಸ value
ರಚನೆಯಾಗುವುದನ್ನು ಖಚಿತಪಡಿಸುತ್ತದೆ.
ಪ್ಯಾಟರ್ನ್ 5: ಕಾಂಟೆಕ್ಸ್ಟ್ ಸೆಲೆಕ್ಟರ್ಗಳು
ಕಾಂಟೆಕ್ಸ್ಟ್ ಸೆಲೆಕ್ಟರ್ಗಳು ಕಾಂಪೊನೆಂಟ್ಗಳಿಗೆ ಕಾಂಟೆಕ್ಸ್ಟ್ ಮೌಲ್ಯದ ನಿರ್ದಿಷ್ಟ ಭಾಗಗಳಿಗೆ ಮಾತ್ರ ಚಂದಾದಾರರಾಗಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತವೆ. ಕಾಂಟೆಕ್ಸ್ಟ್ನ ಇತರ ಭಾಗಗಳು ಬದಲಾದಾಗ ಇದು ಅನಗತ್ಯ ಮರು-ರೆಂಡರ್ಗಳನ್ನು ತಡೆಯುತ್ತದೆ. ಇದನ್ನು ಸಾಧಿಸಲು `use-context-selector` ನಂತಹ ಲೈಬ್ರರಿಗಳು ಅಥವಾ ಕಸ್ಟಮ್ ಅನುಷ್ಠಾನಗಳನ್ನು ಬಳಸಬಹುದು.
ಕಸ್ಟಮ್ ಕಾಂಟೆಕ್ಸ್ಟ್ ಸೆಲೆಕ್ಟರ್ ಬಳಸುವ ಉದಾಹರಣೆ
// useCustomContextSelector.js
import { useContext, useState, useRef, useEffect } from 'react';
function useCustomContextSelector(
context: React.Context,
selector: (value: T) => S
): S {
const value = useContext(context);
const [selected, setSelected] = useState(() => selector(value));
const latestSelector = useRef(selector);
latestSelector.current = selector;
useEffect(() => {
let didUnmount = false;
let lastSelected = selected;
const subscription = () => {
if (didUnmount) {
return;
}
const nextSelected = latestSelector.current(value);
if (!Object.is(lastSelected, nextSelected)) {
lastSelected = nextSelected;
setSelected(nextSelected);
}
};
// You would typically subscribe to context changes here. Since this is a simplified
// example, we'll just call subscription immediately to initialize.
subscription();
return () => {
didUnmount = true;
// Unsubscribe from context changes here, if applicable.
};
}, [value]); // Re-run effect whenever the context value changes
return selected;
}
export default useCustomContextSelector;
// ThemeContext.js (Simplified for brevity)
import React, { createContext, useState, ReactNode } from 'react';
interface Theme {
background: string;
color: string;
}
interface ThemeContextType {
theme: Theme;
setTheme: (newTheme: Theme) => void;
}
const ThemeContext = createContext(undefined);
interface ThemeProviderProps {
children: ReactNode;
initialTheme: Theme;
}
export const ThemeProvider: React.FC = ({ children, initialTheme }) => {
const [theme, setTheme] = useState(initialTheme);
const value: ThemeContextType = {
theme,
setTheme
};
return {children} ;
};
export const useThemeContext = () => {
const context = React.useContext(ThemeContext);
if (!context) {
throw new Error("useThemeContext must be used within a ThemeProvider");
}
return context;
};
export default ThemeContext;
// Usage
import useCustomContextSelector from './useCustomContextSelector';
import ThemeContext, { ThemeProvider, useThemeContext } from './ThemeContext';
function BackgroundComponent() {
const background = useCustomContextSelector(ThemeContext, (context) => context.theme.background);
return Background;
}
function ColorComponent() {
const color = useCustomContextSelector(ThemeContext, (context) => context.theme.color);
return Color;
}
function App() {
const { theme, setTheme } = useThemeContext();
const toggleTheme = () => {
setTheme({ background: theme.background === 'white' ? 'black' : 'white', color: theme.color === 'black' ? 'white' : 'black' });
};
return (
);
}
export default App;
ಈ ಉದಾಹರಣೆಯಲ್ಲಿ, BackgroundComponent
ಥೀಮ್ನ background
ಪ್ರಾಪರ್ಟಿ ಬದಲಾದಾಗ ಮಾತ್ರ ಮರು-ರೆಂಡರ್ ಆಗುತ್ತದೆ, ಮತ್ತು ColorComponent
color
ಪ್ರಾಪರ್ಟಿ ಬದಲಾದಾಗ ಮಾತ್ರ ಮರು-ರೆಂಡರ್ ಆಗುತ್ತದೆ. ಇದು ಸಂಪೂರ್ಣ ಕಾಂಟೆಕ್ಸ್ಟ್ ಮೌಲ್ಯ ಬದಲಾದಾಗ ಅನಗತ್ಯ ಮರು-ರೆಂಡರ್ಗಳನ್ನು ತಪ್ಪಿಸುತ್ತದೆ.
ಪ್ಯಾಟರ್ನ್ 6: ಸ್ಟೇಟ್ನಿಂದ ಆಕ್ಷನ್ಗಳನ್ನು ಪ್ರತ್ಯೇಕಿಸುವುದು
ದೊಡ್ಡ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗಾಗಿ, ಕಾಂಟೆಕ್ಸ್ಟ್ ಮೌಲ್ಯವನ್ನು ಎರಡು ವಿಭಿನ್ನ ಕಾಂಟೆಕ್ಸ್ಟ್ಗಳಾಗಿ ವಿಭಜಿಸುವುದನ್ನು ಪರಿಗಣಿಸಿ: ಒಂದು ಸ್ಟೇಟ್ಗಾಗಿ ಮತ್ತು ಇನ್ನೊಂದು ಆಕ್ಷನ್ಗಳಿಗಾಗಿ (ಡಿಸ್ಪ್ಯಾಚ್ ಫಂಕ್ಷನ್ಗಳು). ಇದು ಕೋಡ್ ಸಂಘಟನೆ ಮತ್ತು ಪರೀಕ್ಷಾ ಸಾಮರ್ಥ್ಯವನ್ನು ಸುಧಾರಿಸುತ್ತದೆ.
ಉದಾಹರಣೆ: ಪ್ರತ್ಯೇಕ ಸ್ಟೇಟ್ ಮತ್ತು ಆಕ್ಷನ್ ಕಾಂಟೆಕ್ಸ್ಟ್ಗಳೊಂದಿಗೆ ಟುಡು ಲಿಸ್ಟ್
// TodoStateContext.js
import React, { createContext, useContext, useReducer, ReactNode } from 'react';
interface Todo {
id: number;
text: string;
completed: boolean;
}
interface TodoState {
todos: Todo[];
}
const initialState: TodoState = {
todos: [],
};
const TodoStateContext = createContext(initialState);
interface TodoStateProviderProps {
children: ReactNode;
}
export const TodoStateProvider: React.FC = ({ children }) => {
const [state] = useReducer(todoReducer, initialState);
return {children} ;
};
export const useTodoState = () => {
return useContext(TodoStateContext);
};
// TodoActionContext.js
import React, { createContext, useContext, Dispatch, ReactNode } from 'react';
type TodoAction =
| { type: 'ADD_TODO'; text: string }
| { type: 'TOGGLE_TODO'; id: number }
| { type: 'DELETE_TODO'; id: number };
const TodoActionContext = createContext | undefined>(undefined);
interface TodoActionProviderProps {
children: ReactNode;
}
export const TodoActionProvider: React.FC = ({children}) => {
const [, dispatch] = useReducer(todoReducer, initialState);
return {children} ;
};
export const useTodoDispatch = () => {
const dispatch = useContext(TodoActionContext);
if (!dispatch) {
throw new Error('useTodoDispatch must be used within a TodoActionProvider');
}
return dispatch;
};
// todoReducer.js
export const todoReducer = (state: TodoState, action: TodoAction): TodoState => {
switch (action.type) {
case 'ADD_TODO':
return {
...state,
todos: [...state.todos, { id: Date.now(), text: action.text, completed: false }],
};
case 'TOGGLE_TODO':
return {
...state,
todos: state.todos.map((todo) =>
todo.id === action.id ? { ...todo, completed: !todo.completed } : todo
),
};
case 'DELETE_TODO':
return {
...state,
todos: state.todos.filter((todo) => todo.id !== action.id),
};
default:
return state;
}
};
// Usage
import { useTodoState, TodoStateProvider } from './TodoStateContext';
import { useTodoDispatch, TodoActionProvider } from './TodoActionContext';
function TodoList() {
const state = useTodoState();
return (
{state.todos.map((todo) => (
-
{todo.text}
))}
);
}
function TodoActions({ todo }) {
const dispatch = useTodoDispatch();
return (
<>
>
);
}
function AddTodo() {
const dispatch = useTodoDispatch();
const [text, setText] = React.useState('');
const handleSubmit = (e) => {
e.preventDefault();
dispatch({ type: 'ADD_TODO', text });
setText('');
};
return (
);
}
function App() {
return (
);
}
export default App;
ಈ ಪ್ರತ್ಯೇಕತೆಯು ಕಾಂಪೊನೆಂಟ್ಗಳಿಗೆ ತಮಗೆ ಬೇಕಾದ ಕಾಂಟೆಕ್ಸ್ಟ್ಗೆ ಮಾತ್ರ ಚಂದಾದಾರರಾಗಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ, ಅನಗತ್ಯ ಮರು-ರೆಂಡರ್ಗಳನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ. ಇದು ರಿಡ್ಯೂಸರ್ ಮತ್ತು ಪ್ರತಿಯೊಂದು ಕಾಂಪೊನೆಂಟ್ ಅನ್ನು ಪ್ರತ್ಯೇಕವಾಗಿ ಯುನಿಟ್ ಟೆಸ್ಟ್ ಮಾಡಲು ಸುಲಭವಾಗಿಸುತ್ತದೆ. ಅಲ್ಲದೆ, ಪ್ರೊವೈಡರ್ ಸುತ್ತುವರಿಯುವ ಕ್ರಮವು ಮುಖ್ಯವಾಗಿದೆ. ActionProvider
StateProvider
ಅನ್ನು ಸುತ್ತುವರಿಯಬೇಕು.
ಅತ್ಯುತ್ತಮ ಅಭ್ಯಾಸಗಳು ಮತ್ತು ಪರಿಗಣನೆಗಳು
- ಕಾಂಟೆಕ್ಸ್ಟ್ ಎಲ್ಲಾ ಸ್ಟೇಟ್ ಮ್ಯಾನೇಜ್ಮೆಂಟ್ ಲೈಬ್ರರಿಗಳನ್ನು ಬದಲಿಸಬಾರದು: ಅತಿ ದೊಡ್ಡ ಮತ್ತು ಸಂಕೀರ್ಣ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ, Redux ಅಥವಾ Zustand ನಂತಹ ಮೀಸಲಾದ ಸ್ಟೇಟ್ ಮ್ಯಾನೇಜ್ಮೆಂಟ್ ಲೈಬ್ರರಿಗಳು ಇನ್ನೂ ಉತ್ತಮ ಆಯ್ಕೆಯಾಗಿರಬಹುದು.
- ಅತಿಯಾದ ಕಾಂಟೆಕ್ಸ್ಟುವಲೈಸೇಶನ್ ತಪ್ಪಿಸಿ: ಪ್ರತಿಯೊಂದು ಸ್ಟೇಟ್ನ ಭಾಗವು ಕಾಂಟೆಕ್ಸ್ಟ್ನಲ್ಲಿ ಇರಬೇಕಾಗಿಲ್ಲ. ನಿಜವಾಗಿಯೂ ಜಾಗತಿಕ ಅಥವಾ ವ್ಯಾಪಕವಾಗಿ ಹಂಚಿಕೊಳ್ಳಲಾದ ಸ್ಟೇಟ್ಗಾಗಿ ಕಾಂಟೆಕ್ಸ್ಟ್ ಅನ್ನು ವಿವೇಚನೆಯಿಂದ ಬಳಸಿ.
- ಕಾರ್ಯಕ್ಷಮತೆ ಪರೀಕ್ಷೆ: ನಿಮ್ಮ ಕಾಂಟೆಕ್ಸ್ಟ್ ಬಳಕೆಯ ಕಾರ್ಯಕ್ಷಮತೆಯ ಪರಿಣಾಮವನ್ನು ಯಾವಾಗಲೂ ಅಳೆಯಿರಿ, ವಿಶೇಷವಾಗಿ ಆಗಾಗ್ಗೆ ನವೀಕರಿಸುವ ಸ್ಟೇಟ್ನೊಂದಿಗೆ ವ್ಯವಹರಿಸುವಾಗ.
- ಕೋಡ್ ಸ್ಪ್ಲಿಟ್ಟಿಂಗ್: ಕಾಂಟೆಕ್ಸ್ಟ್ API ಬಳಸುವಾಗ, ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸಣ್ಣ ತುಣುಕುಗಳಾಗಿ ಕೋಡ್-ಸ್ಪ್ಲಿಟ್ ಮಾಡುವುದನ್ನು ಪರಿಗಣಿಸಿ. ಸ್ಟೇಟ್ನಲ್ಲಿನ ಒಂದು ಸಣ್ಣ ಬದಲಾವಣೆಯು ಅಪ್ಲಿಕೇಶನ್ನ ದೊಡ್ಡ ಭಾಗವನ್ನು ಮರು-ರೆಂಡರ್ ಮಾಡಲು ಕಾರಣವಾದಾಗ ಇದು ವಿಶೇಷವಾಗಿ ಮುಖ್ಯವಾಗಿದೆ.
ತೀರ್ಮಾನ
ರಿಯಾಕ್ಟ್ ಕಾಂಟೆಕ್ಸ್ಟ್ API ಸ್ಟೇಟ್ ಮ್ಯಾನೇಜ್ಮೆಂಟ್ಗಾಗಿ ಒಂದು ಬಹುಮುಖ ಸಾಧನವಾಗಿದೆ. ಈ ಸುಧಾರಿತ ಪ್ಯಾಟರ್ನ್ಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಂಡು ಅನ್ವಯಿಸುವ ಮೂಲಕ, ನೀವು ಸಂಕೀರ್ಣ ಸ್ಟೇಟ್ ಅನ್ನು ಪರಿಣಾಮಕಾರಿಯಾಗಿ ನಿರ್ವಹಿಸಬಹುದು, ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಬಹುದು, ಮತ್ತು ಹೆಚ್ಚು ನಿರ್ವಹಿಸಬಲ್ಲ ಮತ್ತು ಸ್ಕೇಲೆಬಲ್ ರಿಯಾಕ್ಟ್ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ನಿರ್ಮಿಸಬಹುದು. ನಿಮ್ಮ ನಿರ್ದಿಷ್ಟ ಅಗತ್ಯಗಳಿಗಾಗಿ ಸರಿಯಾದ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಮತ್ತು ನಿಮ್ಮ ಕಾಂಟೆಕ್ಸ್ಟ್ ಬಳಕೆಯ ಕಾರ್ಯಕ್ಷಮತೆಯ ಪರಿಣಾಮಗಳನ್ನು ಎಚ್ಚರಿಕೆಯಿಂದ ಪರಿಗಣಿಸಲು ಮರೆಯದಿರಿ.
ರಿಯಾಕ್ಟ್ ವಿಕಸನಗೊಂಡಂತೆ, ಕಾಂಟೆಕ್ಸ್ಟ್ API ಸುತ್ತಲಿನ ಅತ್ಯುತ್ತಮ ಅಭ್ಯಾಸಗಳು ಕೂಡ ವಿಕಸನಗೊಳ್ಳುತ್ತವೆ. ಹೊಸ ತಂತ್ರಗಳು ಮತ್ತು ಲೈಬ್ರರಿಗಳ ಬಗ್ಗೆ ಮಾಹಿತಿ ಹೊಂದಿರುವುದು ಆಧುನಿಕ ವೆಬ್ ಅಭಿವೃದ್ಧಿಯ ಸ್ಟೇಟ್ ಮ್ಯಾನೇಜ್ಮೆಂಟ್ ಸವಾಲುಗಳನ್ನು ನಿಭಾಯಿಸಲು ನೀವು ಸಜ್ಜಾಗಿದ್ದೀರಿ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸುತ್ತದೆ. ಇನ್ನೂ ಸೂಕ್ಷ್ಮ-ಗ್ರೇನ್ಡ್ ರಿಯಾಕ್ಟಿವಿಟಿಗಾಗಿ ಸಿಗ್ನಲ್ಗಳೊಂದಿಗೆ ಕಾಂಟೆಕ್ಸ್ಟ್ ಬಳಸುವಂತಹ ಉದಯೋನ್ಮುಖ ಪ್ಯಾಟರ್ನ್ಗಳನ್ನು ಅನ್ವೇಷಿಸುವುದನ್ನು ಪರಿಗಣಿಸಿ.