#react-native #expo
#реагировать-родной #выставка #react-native
Вопрос:
У меня есть экран, который содержит многие из тех же CustomSlider
компонентов. Я хотел бы получить значения ползунков из каждого ползунка.
Какова наилучшая практика для выполнения этого в react native?
Вот минимальный рабочий пример с тремя ползунками:
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import MultiSlider from "@ptomasroos/react-native-multi-slider";
class CustomSlider extends Component {
constructor(props) {
super(props)
this.state = {
multiSliderValue: [1, 9]
}
}
multiSliderValuesChange = values => {
this.setState({multiSliderValue: values});
};
render(){
return (
<MultiSlider
values={this.state.multiSliderValue}
onValuesChange={this.multiSliderValuesChange}
min={0}
max={10}
step={1}
/>
)
}
}
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
};
}
get_slider_values = () => {
// what is best practice to access the values of every slider here?
// eg an object like this
const slider_values = [[1.4, 7.4], [4.3, 7.0], [1.9, 3.2]]
return slider_values
}
render() {
return (
<View style={{alignItems: 'center', justifyContent: 'center', padding: 50}}>
<CustomSlider />
<CustomSlider />
<CustomSlider />
<Text>{`The slider values are: ` JSON.stringify(this.get_slider_values())}</Text>
</View>
);
}
}
Ответ №1:
Нет необходимости в сложном решении. Способ, которым я бы справился с этим, — это управлять состоянием в родительском компоненте. CustomSlider
На самом деле не нужно знать его состояние. Поскольку родительский компонент должен знать состояние ползунков, лучше обращаться с этим там.
Итак, поскольку родительский компонент будет обрабатывать состояние, это означает, что нам нужно внести некоторые изменения в то, что вы делаете.
- Установите начальные значения в родительском компоненте для состояния каждого из ползунков. Это важно, это означает, что даже если пользователь не прикасается к ползункам, мы знаем их значения.
- Передайте каждому из ползунков функцию, которая вызывает обратный вызов родительского компонента.
- Поскольку родительский компонент контролирует состояние, мы можем удалить состояние из
CustomSlider
. Это дает несколько вариантов, которые мы могли бы оставить как aComponent
, изменить наPureComponent
или пойти еще дальше и изменить на aFunctional Component
Если слайдеру действительно не нужно знать свое состояние, то последний вариант должен быть наилучшим для производительности.
Вот как я бы реорганизовал ваш App.js
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
sliderValues: [[1, 9],[1, 9],[1, 9]] // we should control the state here
};
}
// this uses function currying to bind the function and pass a value to it
onChange = (index) => (values) => {
this.setState( prevState => {
let sliderValues = prevState.sliderValues;
sliderValues[index] = values;
return {
sliderValues
}
})
}
render() {
return (
<View style={{alignItems: 'center', justifyContent: 'center', padding: 50}}>
<CustomSlider intialValues={this.state.sliderValues[0]} onChange={this.onChange(0)}/>
<CustomSlider intialValues={this.state.sliderValues[1]} onChange={this.onChange(1)}/>
<CustomSlider intialValues={this.state.sliderValues[2]} onChange={this.onChange(2)}/>
<Text>{`The slider values are: ` JSON.stringify(this.state.sliderValues)}</Text>
</View>
);
}
}
Обратите внимание, что на самом деле нам не нужна функция для получения значений ползунков, поскольку они хранятся в состоянии. Это означает, что мы можем получить доступ к значениям ползунков напрямую с помощью this.state.sliderValues
.
Вот ваш CustomComponent
переработанный для работы с приведенным выше кодом:
class CustomSlider extends Component { // this could easily be swapped for a PureComponent
render(){
return (
<MultiSlider
values={this.props.intialValues}
onValuesChange={this.props.onChange}
min={0}
max={10}
step={1}
/>
)
}
Обратите внимание, что ему вообще не нужно управлять состоянием, поскольку его обрабатывает родительский компонент. Это также означает, что мы можем удалить много кода, который на самом деле не нужен. Вот почему я думаю, что мы можем пойти на один шаг дальше и сделать это Functional Component
const CustomSlider = ({intialValues, onChange}) => {
return (
<MultiSlider
values={intialValues}
onValuesChange={onChange}
min={0}
max={10}
step={1}
/>
)
}
Однако, если CustomSlider
необходимо знать свое состояние, потому что оно выполняет нечто большее, чем захват значений ползунка, тогда вы можете легко добавить к нему состояние, используя его как Component
или a PureComponent
.
Перекус
Вот краткое описание работы приведенного выше кода. Я показал все три возможных компонента и использовал их в App.js
. В том, как они выглядят, нет большой разницы, но ваш вариант использования определит, какой из них вы используете. https://snack.expo.io/@andypandy/multisliders
Лучшая практика
Лучше всего использовать самое простое решение, которое вы можете найти. В идеале это было бы a Functional Component
, затем a PureComponent
и, наконец, a Component
. Также важно подумать о том, где и как будет использоваться состояние. Некоторые вопросы, которые я задаю себе, это:
- Действительно ли компоненту нужно знать свое собственное состояние?
- Где я планирую использовать это состояние?
- Как долго мне нужны эти значения состояния?
- Нужно ли мне сохранять это состояние?
- Какие инструменты доступны мне на основе того, что я использую в настоящее время?
- Действительно ли мне нужно добавить еще одну зависимость или больше, чтобы заставить это работать?
Если вам нужны значения из ползунков в нескольких местах вашего приложения, вы можете использовать некоторые функции, предоставляемые react-native
, или вашу навигацию для передачи этих значений. Redux и MobX — это большие накладные расходы с точки зрения сложности, и их действительно следует использовать, только если вам нужна глобальная система управления состоянием, в большинстве случаев их можно избежать.
Ответ №2:
Вы можете динамически сохранять состояние с помощью некоторого ключа, присвоенного каждому дочернему компоненту, и получать доступ к каждому состоянию с помощью ключа, который вы ему даете.
Ответ №3:
Один из способов — передать замыкание из родительского компонента в CustomSlider
s в качестве реквизита и отслеживать изменения.
<CustomSlider idx={n}
theClosurePassedThrough= (n, values) => {
// update the parents states here accordingly
}
>
Затем вызовите это закрытие в соответствующее время.
multiSliderValuesChange = values => {
this.setState({multiSliderValue: values});
this.props.theClosurePassedThrough(this.props.idx, values);
};
Однако наилучшей практикой является использование MobX или Redux.