React Native (с Redux) анимирует Switch программно
У меня есть компонент, который имеет компонент Switch внутри. Весь этот компонент кликабелен. Когда вы щелкаете по этому компоненту, он запускает диспетчеризацию (которая изменяет избыточное хранилище) и вызывает повторную визуализацию этого компонента. Мне нужно не перерисовать весь компонент, а просто анимировать этот компонент Switch в правильное состояние.
Что-то вроде этого
<TouchableOpacity onPress={onPress}>
<Text>{this.props.title}</Text>
<Switch value={this.state.active}/>
</TouchableOpacity>
Любая идея?
Я нахожу это довольно распространенным случаем использования и знаю, что попаду во множество подобных сценариев, поэтому мне нужно такое поведение, но я не могу найти никаких примеров или решений в Интернете. Может быть, я просто что-то упустил.
Спасибо
--- РЕДАКТИРОВАТЬ ---
Я тоже попробовал это. Я пытался отключить обновление с помощью shouldComponentUpdate, я пытался установить состояние только в willRecieveProps и / или переключении, даже без переключения. Я также пытался играть с LayoutAnimation. Но ничего не работает. this.setState() просто не анимирует компонент Switch. Я также пытался играть с this._switch._rctSwitch.setNativeProps({ value: nextProps.active }), но это тоже не работает (и пахнет из-за _rctSwitch).
class ViewWithSwitchInside extends React.Component {
constructor(props) {
super(props)
this.toggle = this.toggle.bind(this);
this.state = {
active: props.active
}
}
componentWillReceiveProps(nextProps) {
if (this.state.active != nextProps.active) {
this.setState({ active: nextProps.active })
}
}
toggle() {
let newValue = !this.state.active
this.setState({
active: newValue,
})
if (typeof this.props.onClick === 'function') {
this.props.onClick(newValue)
}
}
render() {
return (
<TouchableWithoutFeedback onPress={this.toggle}>
<View>
<Text>{this.props.title}</Text>
<Switch value={this.state.active} />
</View>
</TouchableWithoutFeedback>
)
}
}
1 ответ
Вы не можете визуализировать только одного потомка от вашего родительского компонента. Даже если бы вы каким-то образом смогли изменить значение переменной, от которой зависит Switch, оно не будет отображаться, пока вы не выполните рендеринг родительского компонента.
Я попытался использовать глобальную переменную для установки значения переключателя, я также предотвратил повторный рендеринг родительского компонента, используя shouldComponentUpdate()
которые вы можете прочитать больше здесь
Это мои результаты:
Это начальное состояние моего приложения. Для этой глобальной переменной задано значение false, а родительский компонент уже обработан.
Теперь я изменяю глобальную переменную на true, нажав на View
вокруг Switch
и это меняется
Но визуально ничего не меняется, изменилась только переменная, а не переключатель.
Я тогда меняю state
(несущественное изменение Switch
компонент), нажав "Re-render" текст в нижней части экрана, и это происходит:
Это код приложения выше:
var isActive = false; //global variable
class Test extends Component {
constructor(props) {
super(props);
this.state={active:false, irrelevantState: true};
}
test(foo){
console.log("Attempting to change", foo);
isActive = foo;
}
shouldComponentUpdate(nextProps, nextState){
if(this.state.active != nextState.active){//If the new state is different than the previous, stop rendering.
this.test(nextState.active);
return false;
}else { //else, re-render everything
return true;
}
}
render(){
console.log("Test re-render");
return(
<View style={{flex:1}}>
<TouchableOpacity onPress={()=>{this.setState({active:!this.state.active})}} style={{flex:1, marginTop:20}}>
<Text>Test Component</Text>
<Switch value={isActive}/>
</TouchableOpacity>
<TouchableOpacity onPress={()=>{this.setState({active:true})}} style={{flex:1, marginTop:20}}>
<Text>Test Component</Text>
<Switch value={isActive}/>
</TouchableOpacity>
<TouchableOpacity style={{height:20}} onPress={()=>this.setState({irrelevantState:false})}>
<Text> Re-render</Text>
</TouchableOpacity>
</View>
)
}
}
Лучше всего найти умный способ перерисовки только тогда, когда this.state.active
и другие необходимые состояния для вашего приложения для изменения функций, игнорируя другие изменения.