0
# Higher-Order Component
1
2
Higher-order component pattern for injecting cookie functionality into class components or components that need cookie access via props rather than hooks.
3
4
## Capabilities
5
6
### withCookies HOC
7
8
Higher-order component that wraps a component and injects cookie-related props, providing an alternative to the `useCookies` hook for class components or when prop-based access is preferred.
9
10
```typescript { .api }
11
/**
12
* Higher-order component that injects cookie functionality via props
13
* @param WrappedComponent - Component to enhance with cookie props
14
* @returns Enhanced component with cookie props injected
15
*/
16
function withCookies<T extends ReactCookieProps>(
17
WrappedComponent: React.ComponentType<T>,
18
): React.ComponentType<Omit<T, keyof ReactCookieProps>>;
19
```
20
21
**Injected Props:**
22
- `cookies`: Cookies instance with get/set/remove methods
23
- `allCookies`: Object containing all current cookies as key-value pairs
24
25
**Static Properties:**
26
- `WrappedComponent`: Reference to the original component
27
- `displayName`: Component display name for debugging
28
29
**Usage Examples:**
30
31
```typescript
32
import React, { Component } from 'react';
33
import { withCookies, Cookies, ReactCookieProps } from 'react-cookie';
34
35
// Class component example
36
interface Props extends ReactCookieProps {
37
cookies: Cookies;
38
allCookies: { [name: string]: any };
39
title: string;
40
}
41
42
interface State {
43
username: string;
44
}
45
46
class UserProfile extends Component<Props, State> {
47
constructor(props: Props) {
48
super(props);
49
50
this.state = {
51
username: props.cookies.get('username') || ''
52
};
53
}
54
55
handleLogin = (username: string) => {
56
const { cookies } = this.props;
57
cookies.set('username', username, { path: '/' });
58
this.setState({ username });
59
};
60
61
handleLogout = () => {
62
const { cookies } = this.props;
63
cookies.remove('username', { path: '/' });
64
this.setState({ username: '' });
65
};
66
67
render() {
68
const { title, allCookies } = this.props;
69
const { username } = this.state;
70
71
return (
72
<div>
73
<h1>{title}</h1>
74
{username ? (
75
<div>
76
<p>Welcome, {username}!</p>
77
<button onClick={this.handleLogout}>Logout</button>
78
</div>
79
) : (
80
<button onClick={() => this.handleLogin('john_doe')}>Login</button>
81
)}
82
<details>
83
<summary>All Cookies</summary>
84
<pre>{JSON.stringify(allCookies, null, 2)}</pre>
85
</details>
86
</div>
87
);
88
}
89
}
90
91
// Enhance component with cookie functionality
92
const EnhancedUserProfile = withCookies(UserProfile);
93
94
// Usage - note that cookie props are automatically injected
95
function App() {
96
return (
97
<CookiesProvider>
98
<EnhancedUserProfile title="My App" />
99
</CookiesProvider>
100
);
101
}
102
103
// Functional component example
104
interface FunctionalProps extends ReactCookieProps {
105
cookies: Cookies;
106
allCookies: { [name: string]: any };
107
label: string;
108
}
109
110
function CookieDisplay({ cookies, allCookies, label }: FunctionalProps) {
111
const handleSetCookie = () => {
112
cookies.set('demo', new Date().toISOString());
113
};
114
115
return (
116
<div>
117
<h2>{label}</h2>
118
<button onClick={handleSetCookie}>Set Demo Cookie</button>
119
<p>Demo cookie: {cookies.get('demo')}</p>
120
<p>All cookies: {Object.keys(allCookies).length}</p>
121
</div>
122
);
123
}
124
125
const EnhancedCookieDisplay = withCookies(CookieDisplay);
126
```
127
128
### Cookies Instance Methods
129
130
The `cookies` prop injected by `withCookies` provides direct access to all cookie management methods.
131
132
```typescript { .api }
133
interface Cookies {
134
/** Get a single cookie value */
135
get(name: string, options?: CookieGetOptions): any;
136
/** Get all cookies as an object */
137
getAll(options?: CookieGetOptions): { [name: string]: any };
138
/** Set a cookie value */
139
set(name: string, value: any, options?: CookieSetOptions): void;
140
/** Remove a cookie */
141
remove(name: string, options?: CookieSetOptions): void;
142
/** Add listener for cookie changes */
143
addChangeListener(callback: () => void): void;
144
/** Remove cookie change listener */
145
removeChangeListener(callback: () => void): void;
146
/** Manually update cookies from browser */
147
update(): void;
148
}
149
```
150
151
**Direct cookie manipulation:**
152
153
```typescript
154
class AdvancedCookieComponent extends Component<Props> {
155
componentDidMount() {
156
const { cookies } = this.props;
157
158
// Get single cookie
159
const theme = cookies.get('theme');
160
161
// Get all cookies
162
const allCookies = cookies.getAll();
163
164
// Set cookie with options
165
cookies.set('lastVisit', new Date().toISOString(), {
166
expires: new Date(Date.now() + 86400000), // 24 hours
167
secure: true,
168
sameSite: 'strict'
169
});
170
171
// Remove cookie (must match original path/domain)
172
cookies.remove('temporary', { path: '/' });
173
174
// Listen for cookie changes
175
cookies.addChangeListener(this.handleCookieChange);
176
}
177
178
componentWillUnmount() {
179
this.props.cookies.removeChangeListener(this.handleCookieChange);
180
}
181
182
handleCookieChange = () => {
183
// Force component update when cookies change
184
this.forceUpdate();
185
};
186
187
render() {
188
return <div>Component content</div>;
189
}
190
}
191
```
192
193
### Component Lifecycle Integration
194
195
The HOC automatically handles cookie change detection and component updates.
196
197
```typescript
198
class LifecycleExample extends Component<Props> {
199
componentDidMount() {
200
// HOC automatically listens for cookie changes
201
console.log('Component mounted with cookies:', this.props.allCookies);
202
}
203
204
componentDidUpdate(prevProps: Props) {
205
// Compare cookie changes
206
if (prevProps.allCookies !== this.props.allCookies) {
207
console.log('Cookies changed:', this.props.allCookies);
208
}
209
}
210
211
render() {
212
// Component automatically re-renders when cookies change
213
return <div>Cookie count: {Object.keys(this.props.allCookies).length}</div>;
214
}
215
}
216
217
const EnhancedLifecycleExample = withCookies(LifecycleExample);
218
```
219
220
### Static Properties Access
221
222
Access the original component and display name through static properties.
223
224
```typescript
225
const OriginalComponent = ({ title }: { title: string }) => <h1>{title}</h1>;
226
const EnhancedComponent = withCookies(OriginalComponent);
227
228
// Access original component
229
console.log(EnhancedComponent.WrappedComponent === OriginalComponent); // true
230
231
// Display name for debugging
232
console.log(EnhancedComponent.displayName); // "withCookies(OriginalComponent)"
233
234
// Use in React DevTools or testing
235
expect(EnhancedComponent.WrappedComponent).toBe(OriginalComponent);
236
```
237
238
### TypeScript Integration
239
240
Proper TypeScript usage with the HOC pattern.
241
242
```typescript
243
// Define props interface that extends ReactCookieProps
244
interface MyComponentProps extends ReactCookieProps {
245
cookies: Cookies;
246
allCookies: { [name: string]: any };
247
// Your custom props
248
title: string;
249
onSave?: (data: any) => void;
250
}
251
252
class MyComponent extends Component<MyComponentProps> {
253
render() {
254
const { cookies, allCookies, title, onSave } = this.props;
255
// TypeScript knows about all props including injected ones
256
return <div>{title}</div>;
257
}
258
}
259
260
// HOC removes cookie-related props from required props
261
const Enhanced = withCookies(MyComponent);
262
263
// Usage - only custom props are required
264
<Enhanced title="Hello" onSave={handleSave} />
265
```