如何将浮点数从 sqlite db 映射到 TextInput 并在 React Native 和 redux 中向后映射?

How to map floating number from sqlite db to TextInput and backward in React Native and redux?

我正在从 sqlite 数据库中获取一个浮点数并将其设置为 redux 状态。比起我向 TextInput 组件显示此 属性。为此,我必须将浮点数转换为字符串。在编辑值时,我触发事件 onChangeText,将字符串转换为浮点数并更新 redux 状态。

当我清除 TextInput 中点后的最后一个字符时,由于将 属性 值从数字转换为字符串,我的点也被清除。在这种情况下我怎样才能节省点数?在 react-redux 中使用浮动值的正确方法是什么?

我的自定义组件代码:

import React from 'react';
import PropTypes from 'prop-types';
import { View, TextInput } from 'react-native';

class FormFieldNumeric extends React.PureComponent {

    constructor() {
        super();
        this.state = {
            textValue: ''
        }
    }

    componentWillReceiveProps(nextProps, nextContext) {
        if (parseFloat(this.state.textValue) !== nextProps.value) {
            this.setState({
                textValue: nextProps.value ? String(nextProps.value) : ''
            })
        }
    }

    onChangeText = text => {

        if (!text) {
            this.changeValue('');
            return;
        }

        if (text.length === 1) {
            if (!'0123456789'.includes(text)) {
                return;
            }
        }

        const lastSymbol = text[text.length - 1];
        if ('1234567890.,'.includes(lastSymbol)) {

            if (text.split('').filter(ch => ch === '.' || ch === ',').length > 1) {
                return;
            }

            if (lastSymbol === ',') {
                this.changeValue(this.state.textValue + '.');
                return;
            }

            this.changeValue(text);

        }

    };

    changeValue = text => {
        this.setState({
            textValue: text
        });
        this.props.onChange(text ? parseFloat(text) : 0);
    };

    render() {

        const { caption, value, onChange, placeholder } = this.props;

        return (
            <View>
                <TextInput
                    value={this.state.textValue}
                    keyboardType="numeric"
                    onChangeText={this.onChangeText}
                    placeholder={placeholder}
                    maxLength={10}
                />
            </View>
        )

    }
}

FormFieldNumeric.propType = {
    placeholder: PropTypes.string, 
    value: PropTypes.number, 
    onChange: PropTypes.func.isRequired
};

export default FormFieldNumeric;

一个选项是仅当用户完成编辑而不是每次击键时才有效并更新 redux 存储中的值。您可以使用 onEndEditing TextInput 回调来完成此操作。

了解我的错误。当我试图在两个地方保持相同的状态时,我陷入了反模式陷阱。 This article 详细描述了这一点。根据文章的建议,我使用了一个不受控制的组件,并将状态直接存储在组件中,我只传递 属性 来初始化值。

import React from 'react';
import PropTypes from 'prop-types';
import { View, TextInput } from 'react-native';

class FormFieldNumeric extends React.PureComponent {

    constructor(props) {
        super(props);
        this.state = {
            defaultValue: props.defaultValue,
            textValue: this.floatToTextValue(props.defaultValue)
        }
    }

    floatToTextValue = value => {
        return value ? String(value) : '';
    };

    render() {

        const { placeholder } = this.props;

        return (
            <View>
                <TextInput
                    value={this.state.textValue}
                    keyboardType="numeric"
                    onChangeText={this.onChangeText}
                    placeholder={placeholder}
                />
            </View>
        )

    }
}

FormFieldNumeric.defaultValue = {
    placeholder: '',
    defaultValue: 0
};

FormFieldNumeric.propType = {
    placeholder: PropTypes.string, 
    defaultValue: PropTypes.number, 
    onChange: PropTypes.func.isRequired
};

export default FormFieldNumeric;

而为了组件加载redux状态后更新值,我在父组件中做了_isLoading字段,默认为true,加载数据后变为false。我把这个值作为父组件的键 属性 传递了:

class ParentComponent extends React.PureComponent {

    _isLoading = false;

    async componentDidMount() {
        await this.props.onCreate();
        this._isLoading = false;
    }  

    render() {
        return (
            <View key={this._isLoading}>
                <FormFieldNumeric
                    defaultValue={this.props.cashSum}
                    onChange={this.onChangeCashSum}
                    placeholder="0.00"
                />
            </View>
        )
    }

}