0
# Programmatic Control
1
2
Reference-based methods for programmatic value updates and control, allowing external manipulation of slider values without user interaction.
3
4
## Capabilities
5
6
### Slider Reference Interface
7
8
Interface for programmatically controlling slider values through React refs.
9
10
```typescript { .api }
11
interface SliderRef {
12
/**
13
* Programmatically update the slider value
14
* @param value - New value to set (must be within min/max range)
15
*/
16
updateValue(value: number): void;
17
}
18
19
type SliderReferenceType =
20
| (React.MutableRefObject<SliderRef> & React.LegacyRef<Slider>)
21
| undefined;
22
23
interface SliderRefProps {
24
/**
25
* Reference object for programmatic control
26
*/
27
ref?: SliderReferenceType;
28
}
29
```
30
31
**Usage Examples:**
32
33
```typescript
34
import React, { useRef, useState } from 'react';
35
import { View, Text, Button } from 'react-native';
36
import Slider from '@react-native-community/slider';
37
import type { SliderRef } from '@react-native-community/slider';
38
39
// Basic programmatic control
40
function ProgrammaticSlider() {
41
const sliderRef = useRef<SliderRef>(null);
42
const [currentValue, setCurrentValue] = useState(50);
43
44
const setToMinimum = () => {
45
sliderRef.current?.updateValue(0);
46
};
47
48
const setToMaximum = () => {
49
sliderRef.current?.updateValue(100);
50
};
51
52
const setToMiddle = () => {
53
sliderRef.current?.updateValue(50);
54
};
55
56
return (
57
<View>
58
<Text>Current Value: {currentValue}</Text>
59
60
<Slider
61
ref={sliderRef}
62
style={{width: 300, height: 40}}
63
minimumValue={0}
64
maximumValue={100}
65
value={currentValue}
66
onValueChange={setCurrentValue}
67
/>
68
69
<View style={{flexDirection: 'row', gap: 10}}>
70
<Button title="Min (0)" onPress={setToMinimum} />
71
<Button title="Mid (50)" onPress={setToMiddle} />
72
<Button title="Max (100)" onPress={setToMaximum} />
73
</View>
74
</View>
75
);
76
}
77
78
// Animated value updates
79
function AnimatedSlider() {
80
const sliderRef = useRef<SliderRef>(null);
81
const [currentValue, setCurrentValue] = useState(0);
82
const [isAnimating, setIsAnimating] = useState(false);
83
84
const animateToValue = (targetValue: number) => {
85
if (isAnimating) return;
86
87
setIsAnimating(true);
88
const startValue = currentValue;
89
const difference = targetValue - startValue;
90
const duration = 1000; // 1 second
91
const steps = 60; // 60 FPS
92
const stepValue = difference / steps;
93
94
let currentStep = 0;
95
const interval = setInterval(() => {
96
currentStep++;
97
const newValue = startValue + (stepValue * currentStep);
98
99
sliderRef.current?.updateValue(newValue);
100
101
if (currentStep >= steps) {
102
clearInterval(interval);
103
setIsAnimating(false);
104
sliderRef.current?.updateValue(targetValue); // Ensure exact final value
105
}
106
}, duration / steps);
107
};
108
109
return (
110
<View>
111
<Text>Animated Value: {currentValue.toFixed(1)}</Text>
112
113
<Slider
114
ref={sliderRef}
115
style={{width: 300, height: 40}}
116
minimumValue={0}
117
maximumValue={100}
118
value={currentValue}
119
onValueChange={setCurrentValue}
120
disabled={isAnimating}
121
/>
122
123
<View style={{flexDirection: 'row', gap: 10}}>
124
<Button
125
title="Animate to 25"
126
onPress={() => animateToValue(25)}
127
disabled={isAnimating}
128
/>
129
<Button
130
title="Animate to 75"
131
onPress={() => animateToValue(75)}
132
disabled={isAnimating}
133
/>
134
</View>
135
</View>
136
);
137
}
138
```
139
140
### External Control Patterns
141
142
Common patterns for controlling sliders from external sources like APIs, timers, or other components.
143
144
**Usage Examples:**
145
146
```typescript
147
import React, { useRef, useState, useEffect } from 'react';
148
import { View, Text, Button } from 'react-native';
149
import Slider from '@react-native-community/slider';
150
151
// Timer-controlled slider
152
function TimerControlledSlider() {
153
const sliderRef = useRef<SliderRef>(null);
154
const [progress, setProgress] = useState(0);
155
const [isRunning, setIsRunning] = useState(false);
156
157
useEffect(() => {
158
if (!isRunning) return;
159
160
const interval = setInterval(() => {
161
setProgress(prev => {
162
const newValue = prev + 1;
163
if (newValue >= 100) {
164
setIsRunning(false);
165
return 100;
166
}
167
sliderRef.current?.updateValue(newValue);
168
return newValue;
169
});
170
}, 100); // Update every 100ms
171
172
return () => clearInterval(interval);
173
}, [isRunning]);
174
175
const startTimer = () => {
176
setIsRunning(true);
177
};
178
179
const stopTimer = () => {
180
setIsRunning(false);
181
};
182
183
const resetTimer = () => {
184
setIsRunning(false);
185
setProgress(0);
186
sliderRef.current?.updateValue(0);
187
};
188
189
return (
190
<View>
191
<Text>Progress: {progress}%</Text>
192
193
<Slider
194
ref={sliderRef}
195
style={{width: 300, height: 40}}
196
minimumValue={0}
197
maximumValue={100}
198
value={progress}
199
onValueChange={setProgress}
200
disabled={isRunning}
201
/>
202
203
<View style={{flexDirection: 'row', gap: 10}}>
204
<Button title="Start" onPress={startTimer} disabled={isRunning} />
205
<Button title="Stop" onPress={stopTimer} disabled={!isRunning} />
206
<Button title="Reset" onPress={resetTimer} />
207
</View>
208
</View>
209
);
210
}
211
212
// Network-controlled slider
213
function NetworkControlledSlider() {
214
const sliderRef = useRef<SliderRef>(null);
215
const [volume, setVolume] = useState(50);
216
const [isLoading, setIsLoading] = useState(false);
217
218
// Simulate API call to update volume
219
const syncWithServer = async (newVolume: number) => {
220
setIsLoading(true);
221
try {
222
// Simulate API call
223
await new Promise(resolve => setTimeout(resolve, 500));
224
225
// Update slider with server response
226
sliderRef.current?.updateValue(newVolume);
227
setVolume(newVolume);
228
} catch (error) {
229
console.error('Failed to sync with server:', error);
230
} finally {
231
setIsLoading(false);
232
}
233
};
234
235
// Simulate receiving updates from server
236
const simulateServerUpdate = () => {
237
const randomVolume = Math.floor(Math.random() * 100);
238
syncWithServer(randomVolume);
239
};
240
241
return (
242
<View>
243
<Text>Volume: {volume}% {isLoading && '(Syncing...)'}</Text>
244
245
<Slider
246
ref={sliderRef}
247
style={{width: 300, height: 40}}
248
minimumValue={0}
249
maximumValue={100}
250
value={volume}
251
onValueChange={(value) => {
252
setVolume(value);
253
// Could trigger debounced API call here
254
}}
255
disabled={isLoading}
256
/>
257
258
<Button
259
title="Simulate Server Update"
260
onPress={simulateServerUpdate}
261
disabled={isLoading}
262
/>
263
</View>
264
);
265
}
266
```
267
268
### Multi-Slider Coordination
269
270
Coordinating multiple sliders programmatically for complex UI scenarios.
271
272
**Usage Examples:**
273
274
```typescript
275
import React, { useRef, useState } from 'react';
276
import { View, Text, Button } from 'react-native';
277
import Slider from '@react-native-community/slider';
278
279
// RGB Color picker with coordinated sliders
280
function RGBColorPicker() {
281
const redSliderRef = useRef<SliderRef>(null);
282
const greenSliderRef = useRef<SliderRef>(null);
283
const blueSliderRef = useRef<SliderRef>(null);
284
285
const [red, setRed] = useState(128);
286
const [green, setGreen] = useState(128);
287
const [blue, setBlue] = useState(128);
288
289
const setPresetColor = (r: number, g: number, b: number) => {
290
redSliderRef.current?.updateValue(r);
291
greenSliderRef.current?.updateValue(g);
292
blueSliderRef.current?.updateValue(b);
293
setRed(r);
294
setGreen(g);
295
setBlue(b);
296
};
297
298
const rgbColor = `rgb(${red}, ${green}, ${blue})`;
299
300
return (
301
<View>
302
<View style={{
303
width: 100,
304
height: 100,
305
backgroundColor: rgbColor,
306
marginBottom: 20,
307
borderRadius: 8,
308
}} />
309
310
<Text>RGB: ({red}, {green}, {blue})</Text>
311
312
<View style={{marginVertical: 10}}>
313
<Text>Red: {red}</Text>
314
<Slider
315
ref={redSliderRef}
316
style={{width: 300, height: 40}}
317
minimumValue={0}
318
maximumValue={255}
319
step={1}
320
value={red}
321
onValueChange={setRed}
322
minimumTrackTintColor="#ff0000"
323
/>
324
</View>
325
326
<View style={{marginVertical: 10}}>
327
<Text>Green: {green}</Text>
328
<Slider
329
ref={greenSliderRef}
330
style={{width: 300, height: 40}}
331
minimumValue={0}
332
maximumValue={255}
333
step={1}
334
value={green}
335
onValueChange={setGreen}
336
minimumTrackTintColor="#00ff00"
337
/>
338
</View>
339
340
<View style={{marginVertical: 10}}>
341
<Text>Blue: {blue}</Text>
342
<Slider
343
ref={blueSliderRef}
344
style={{width: 300, height: 40}}
345
minimumValue={0}
346
maximumValue={255}
347
step={1}
348
value={blue}
349
onValueChange={setBlue}
350
minimumTrackTintColor="#0000ff"
351
/>
352
</View>
353
354
<View style={{flexDirection: 'row', gap: 10, marginTop: 20}}>
355
<Button title="Red" onPress={() => setPresetColor(255, 0, 0)} />
356
<Button title="Green" onPress={() => setPresetColor(0, 255, 0)} />
357
<Button title="Blue" onPress={() => setPresetColor(0, 0, 255)} />
358
<Button title="Black" onPress={() => setPresetColor(0, 0, 0)} />
359
<Button title="White" onPress={() => setPresetColor(255, 255, 255)} />
360
</View>
361
</View>
362
);
363
}
364
365
// Master-slave slider relationship
366
function MasterSlaveSliders() {
367
const masterRef = useRef<SliderRef>(null);
368
const slave1Ref = useRef<SliderRef>(null);
369
const slave2Ref = useRef<SliderRef>(null);
370
371
const [masterValue, setMasterValue] = useState(50);
372
const [slave1Value, setSlave1Value] = useState(25);
373
const [slave2Value, setSlave2Value] = useState(75);
374
375
// When master changes, update slaves proportionally
376
const handleMasterChange = (value: number) => {
377
setMasterValue(value);
378
379
// Update slaves to maintain proportion
380
const slave1Proportion = value * 0.5; // 50% of master
381
const slave2Proportion = Math.min(100, value * 1.5); // 150% of master (clamped)
382
383
slave1Ref.current?.updateValue(slave1Proportion);
384
slave2Ref.current?.updateValue(slave2Proportion);
385
setSlave1Value(slave1Proportion);
386
setSlave2Value(slave2Proportion);
387
};
388
389
return (
390
<View>
391
<Text>Master Control System</Text>
392
393
<View style={{marginVertical: 10}}>
394
<Text>Master: {masterValue.toFixed(1)}</Text>
395
<Slider
396
ref={masterRef}
397
style={{width: 300, height: 40}}
398
minimumValue={0}
399
maximumValue={100}
400
value={masterValue}
401
onValueChange={handleMasterChange}
402
minimumTrackTintColor="#ff6b6b"
403
/>
404
</View>
405
406
<View style={{marginVertical: 10}}>
407
<Text>Slave 1 (50% of Master): {slave1Value.toFixed(1)}</Text>
408
<Slider
409
ref={slave1Ref}
410
style={{width: 300, height: 40}}
411
minimumValue={0}
412
maximumValue={100}
413
value={slave1Value}
414
onValueChange={setSlave1Value}
415
disabled={true} // Controlled by master
416
minimumTrackTintColor="#4ecdc4"
417
/>
418
</View>
419
420
<View style={{marginVertical: 10}}>
421
<Text>Slave 2 (150% of Master): {slave2Value.toFixed(1)}</Text>
422
<Slider
423
ref={slave2Ref}
424
style={{width: 300, height: 40}}
425
minimumValue={0}
426
maximumValue={100}
427
value={slave2Value}
428
onValueChange={setSlave2Value}
429
disabled={true} // Controlled by master
430
minimumTrackTintColor="#45b7d1"
431
/>
432
</View>
433
</View>
434
);
435
}
436
```
437
438
### Error Handling and Validation
439
440
Proper error handling when using programmatic control.
441
442
**Usage Examples:**
443
444
```typescript
445
import React, { useRef, useState } from 'react';
446
import { View, Text, Button, Alert } from 'react-native';
447
import Slider from '@react-native-community/slider';
448
449
function ValidatedSlider() {
450
const sliderRef = useRef<SliderRef>(null);
451
const [value, setValue] = useState(50);
452
const [inputValue, setInputValue] = useState('50');
453
454
const updateSliderSafely = (newValue: number) => {
455
try {
456
// Validate the value is within bounds
457
const minValue = 0;
458
const maxValue = 100;
459
460
if (isNaN(newValue)) {
461
throw new Error('Value must be a number');
462
}
463
464
if (newValue < minValue || newValue > maxValue) {
465
throw new Error(`Value must be between ${minValue} and ${maxValue}`);
466
}
467
468
// Update the slider
469
sliderRef.current?.updateValue(newValue);
470
setValue(newValue);
471
setInputValue(newValue.toString());
472
473
} catch (error) {
474
Alert.alert('Invalid Value', error.message);
475
// Revert input to current valid value
476
setInputValue(value.toString());
477
}
478
};
479
480
const handleTextInput = (text: string) => {
481
setInputValue(text);
482
const numericValue = parseFloat(text);
483
if (!isNaN(numericValue)) {
484
updateSliderSafely(numericValue);
485
}
486
};
487
488
return (
489
<View>
490
<Text>Current Value: {value}</Text>
491
492
<Slider
493
ref={sliderRef}
494
style={{width: 300, height: 40}}
495
minimumValue={0}
496
maximumValue={100}
497
value={value}
498
onValueChange={setValue}
499
/>
500
501
<TextInput
502
style={{
503
borderWidth: 1,
504
borderColor: '#ccc',
505
padding: 8,
506
marginVertical: 10,
507
width: 100,
508
}}
509
value={inputValue}
510
onChangeText={handleTextInput}
511
keyboardType="numeric"
512
placeholder="Enter value"
513
/>
514
515
<View style={{flexDirection: 'row', gap: 10}}>
516
<Button title="Set to 25" onPress={() => updateSliderSafely(25)} />
517
<Button title="Set to 75" onPress={() => updateSliderSafely(75)} />
518
<Button title="Invalid (-10)" onPress={() => updateSliderSafely(-10)} />
519
</View>
520
</View>
521
);
522
}
523
```
524
525
## Types
526
527
### Reference Type Definitions
528
529
```typescript { .api }
530
import type { React } from 'react';
531
532
interface SliderRef {
533
updateValue(value: number): void;
534
}
535
536
type SliderReferenceType =
537
| (React.MutableRefObject<SliderRef> & React.LegacyRef<Slider>)
538
| undefined;
539
540
interface SliderRefProps {
541
ref?: SliderReferenceType;
542
}
543
```
544
545
### Hook Integration Types
546
547
```typescript { .api }
548
// For use with useRef hook
549
type SliderRefHook = React.MutableRefObject<SliderRef | null>;
550
551
// For use with forwardRef pattern
552
type ForwardedSliderRef = React.ForwardedRef<SliderRef>;
553
```