仅在首次渲染时更新状态



使用 react-native,我在父App中创建子组件,并在父App中为数组this.state.objLocation提供它们的位置。

我可以在渲染后直接将初始位置数据放入数组中,但由于我的子组件是可拖动的,因此每次它们在拖动时重新渲染时,都会向数组添加新的位置对象。

我想避免这种情况,我认为在构造函数中创建this.state = { firstRender: true }然后在第一次渲染后使用componentDidMount = () => { this.setState({ firstRender: false }) }将允许我创建一个"门"来停止添加额外的位置对象。

我可以看到,如果我注释掉//componentDidMount = () => { this.setState({ firstRender: false }) }那么我将在我的数组中获得多个条目,但如果它包含在类中,我绝对不会得到。

那么,我对渲染生命周期和componentDidMount的解释可能是不正确的?

这是我的代码。

//应用程序

import React, { Component } from 'react'; 
import { View, Text, } from 'react-native';
import styles from './cust/styles';
import Draggable from './cust/draggable';
const dataArray = [{num: 1,id: 'A',},{num: 2,id: 'B',},{num: 3,id: 'Z',}]
export default class Viewport extends Component {
    constructor(props){
        super(props);
        this.state = {
            dID  : null,
            objLocation: [],
            firstRender: true,
        };
    }
    render(){
        return (
            <View style={styles.mainContainer}>
                <View style={styles.draggableContainer}>
                    <Text>Draggable Container</Text> {dataArray.map( d => { return(
                    <Draggable 
                        id={d.id} 
                        onLayout={ e=> this.onLayout(e)} 
                        onPanResponderGrant={(dID) =>this.setState({ dID })} 
                        onPanResponderRelease={() => this.setState({dID: null})} /> ) })}
                        <View style={[styles.findPoint ]} /> 
                </View>
                <View style={styles.infoBar}>
                    <Text>{this.state.dID ? this.state.dID : ''}</Text>{this.compFrame()}
                </View>
            </View>
        );
    }
    onLayout = (e) => {
      if ( e && this.state.firstRender) {
        const n = e.nativeEvent.layout;
            const position = {
              width: n.width,
              height: n.height,
              x: n.x,
              y: n.y
            }
        console.log(position);
        this.setState({
          objLocation: this.state.objLocation.concat([position])
        });
      }
    }
    componentWillMount = () => {
      console.log("START");
    }
    compFrame = () => {
      return(
        this.state.objLocation.map( d => {<View style={[styles.findPoint2,{left: d.x, top: d.y, width: d.width, height: d.height} ]} ></View>})
        )
    }
    componentDidMount = () => {
      this.setState({firstRender: true })
      console.log(this.state.objLocation.length);
    }
}

可拖动

import React, { Component } from 'react';
import { Text, PanResponder, Animated } from 'react-native';
import styles from './styles';
class Draggable extends Component {
  constructor(props) {
    super(props);
    this.state = {
      pan: new Animated.ValueXY(),
    };
    this.panResponder = PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      onPanResponderGrant: () => {
        this.props.onPanResponderGrant(this.props.id);
      },
      onPanResponderMove: Animated.event([ null, {
          dx: this.state.pan.x,
          dy: this.state.pan.y,
        },
      ]),
      onPanResponderRelease: () => {
        Animated.spring(this.state.pan, { toValue: { x: 0, y: 0 } }).start();
        this.props.onPanResponderRelease();
      },
    });
  }
  render() {
    return (
      <Animated.View
        onLayout={ (e) => this.props.onLayout(e) }
        {...this.panResponder.panHandlers}
        style={[this.state.pan.getLayout(), styles.circleAlt, styles.position]}>
        <Text style={styles.textAlt}>Drag me!</Text>
        <Text style={styles.textNum}>{this.props.id}</Text>
      </Animated.View>
    );
  }
  componentDidMount = () => {
    this.props.onLayout(this.props.dragEvent)
  }
}
export default Draggable;

控制台输出.log

START xxx
0
{width:108,height:108,x:133.5,y:376.5}
{width:108,height:108,x:133.5,y:78.5}
{width:108,height:108,x:133.5,y:227.5}

您可以在 onLayout 函数中设置 firstRender 状态

     onLayout = (e) => {
          if ( e && this.state.firstRender) {
            const n = e.nativeEvent.layout;
            const position = {
                  width: n.width,
                  height: n.height,
                  x: n.x,
                  y: n.y
            }
    console.log(position);
    this.setState({
         firstRender: false,          
         objLocation: this.state.objLocation.concat([position])
    });
  }

}

根据您提供的信息,您的onLayout函数由组件调用,因此它不包含在组件生命周期过程中,因此当组件完成其生命周期时,它会在挂载后进入componentDidMount(不调用onLayout func(,从而将firstRender状态更改为false,因此当您每次从true变为false时拖动组件时。我希望这能解释

我觉得

我已经破解了这个,让它工作,所以请纠正我更正程序。

这是来自App的 onLayout 方法。我包含一个 if 语句,用于检查新位置数组长度是否也等于可拖动项所基于的 dataArray 长度。

它看起来像这样。

onLayout = (e) => {
  if ( this.state.objLocation.length != dataArray.length ) {
    if ( e ) {
      const n = e.nativeEvent.layout;
          const position = {
            width: n.width,
            height: n.height,
            x: n.x,
            y: n.y
          }
      console.log(position);
      this.setState({
        objLocation: this.state.objLocation.concat([position])
      });
    }
  }
}

相关内容

  • 没有找到相关文章

最新更新