【问题标题】:How can I get values from input components (study purposes)?如何从输入组件中获取值(学习目的)?
【发布时间】:2022-01-12 13:30:53
【问题描述】:

我的问题是我试图通过 API 调用处理我的输入值,用户定义了他想要的输入。

这是我获取值的地方:

 const handleClick = buttonTitle => async () => {
    await renderField(buttonTitle).then(response => {               
      navigation.navigate('FormScreen', {
        collectionKey: buttonTitle.slice(7),
        paramKey: JSON.stringify(response),
      });     
  });
  };

渲染字段是一个API调用,它返回我{"message": [{"_id": "618e4c23db08f70b719f3655", "author": "adicionarei posteriormente", "ceatedAt": "2021-11-12 08:12:32", "field": "abc", "fieldtype": "Text"}, {"_id": "618e4c9ddb08f70b719fae37", "author": "adicionarei posteriormente", "ceatedAt": "2021-11-12 08:14:35", "field": "Animal", "fieldtype": "Text"}]}

然后我有我的表单组件,我在其中获得了一些需要的组件并显示给用户:

const FormScreen = ({route, navigation}) => {
  return (
    <Container>
      <InputBody route={route.params.paramKey} navigation={navigation} />
    </Container>
    // => handle submit Input it in here ?
  );
};

对于我的inputbody 组件,我有以下代码(请记住(body.map 是 api 调用响应):

  return (
    <>   
    {Object.keys(Body).length > 0 ? (     
      Body.map(item => (
        <React.Fragment key={uuid.v4()}><Texto>{item.field}</Texto>  
           {renderContent(item.fieldtype,item.field)}
        </React.Fragment>
      ))
    ) : (
      <ActivityIndicator size="large" color="#eb6b09" />
    )}
    </>
  )
}

然后我有我的渲染内容(我得到字段的类型为string 和字段的名称为string)。

function renderContent(type,field) {
    switch(type) {     
      case 'Numeric':
      return <NumberInput key={field} keyboardType="numeric" />
     case 'Text':
      return <TextInput key={field} />
    }
  }

记住:每个字段类型可以出现多次。 (例如:我可以有一个表单有超过 1 个文本输入),那么我的问题是:我如何处理我的输入值,知道它可以有任何类型的输入(Numeric or Text)?

obs:我可以显示任何类型的信息。

【问题讨论】:

    标签: javascript react-native function jsx


    【解决方案1】:

    如果你只想要this input types,你可以这样:

    首先,定义将字段类型映射到 html 输入类型的对象:

    const inputTypesMapper = {
      Numeric: "number",
      Text: "text",
      Boolean: "checkbox"
    };
    

    因此您可以将它们呈现如下:

    <div className="App">
     {data.message.map(({ fieldtype, field }) => (
       <input type={inputTypesMapper[fieldtype]} defaultValue={field} />
     ))}
    </div>
    

    Here you go an example

    但是如果你想为每个字段类型渲染不同的组件,你可以这样做:

    首先,定义将字段类型映射到 html 输入类型的对象:

    const inputTypesMapper = {
      Text: ({ value }) => {
        return <input type={"text"} defaultValue={value} />;
      },
      MultipleOptions: ({ value }) => {
        return (
          <select>
            {value.map(({ id, value }) => {
              return <option value={id}>{value}</option>;
            })}
          </select>
        );
      }
    };
    

    因此您可以将它们呈现如下:

      return (
        <div className="App">
          {data.message.map(({ fieldtype, field }) => {
            const renderInput = inputTypesMapper[fieldtype];
    
            return renderInput({ value: field });
          })}
        </div>
      );
    

    Here you go an example

    【讨论】:

      【解决方案2】:
      
          const Input = ({value,keyboardType,onChange})=>{
            return(
              <TextInput value={value} keyboardType={keyboardType} onChangeText={onChange} /> 
            )
          }
      
      
          const [payload,setPayload] = useState({});
      
          const onValue=(e,field)=>{
            let tempPayload = {...payload};
            tempPayload[field] = e;
            setPayload(tempPayload)
          }
      
      
          const renderComponent = (fieldObj)=>{
            switch(fieldObj.type):
              case "Text":
                return <Input keyboardType="default" onChange={(e)=>onValue(e,fieldObj.field)} value={payload[fieldObj.field]||""}/>
              case "Number":
                return <Input keyboardType="numeric" onChange={(e)=>onValue(e,fieldObj.field)} value={payload[fieldObj.field]||""} />
              case "Dropdown":
                return <Dropdown options={fieldObj.options} />  //if you want to add dropdown, radio buttons etc in future
          }
      
      

      这个想法很简单。将表单字段中的值存储在对象payload 中。名称是字段的名称,例如。动物。该值是该字段的值。您还可以使用从 api 获得的所有键及其值初始化为空或默认值的对象。因此,如果我们渲染的字段是 Animal 和 Car。有效载荷将是

      {
        'Animal':'Tiger',
        'Car':'BMW'
      }
      

      这是使用 onValue 函数处理的。您还可以在此函数中添加验证。例如,如果您使用 api 为该字段传递正则表达式,则可以使用正则表达式验证值。

      【讨论】:

      • 谢谢你的回答,但是当我把这个我的键盘隐藏在改变的情况下,在我按下键盘的每个键后隐藏,你知道为什么吗? @user9747
      • 通常在Input组件的父组件重新渲染时发生。
      【解决方案3】:

      这有点hacky所以我简化了它,我认为你应该了解它背后的逻辑。

      import React, { useState } from 'react';
      import { TextInput } from 'react-native';
      
      const createInitialState = (inputList) => {
        return inputList.reduce((accumulator, currentValue) => {
          return {
            ...accumulator,
            [currentValue.field]: '',
          };
        }, {});
      };
      
      
      const SomeScreen = () => {
        const initialDataPassed = [
          {
            '_id': '618e4c23db08f70b719f3655',
            'author': 'adicionarei posteriormente',
            'ceatedAt': '2021-11-12 08:12:32',
            'field': 'abc',
            'fieldType': 'Text',
          }, {
            '_id': '618e4c9ddb08f70b719fae37',
            'author': 'adicionarei posteriormente',
            'ceatedAt': '2021-11-12 08:14:35',
            'field': 'Animal',
            'fieldType': 'Text',
          },
          {
            '_id': '618e4c9ddb08f70b719fae37',
            'author': 'adicionarei posteriormente',
            'ceatedAt': '2021-11-12 08:14:35',
            'field': 'Animal',
            'fieldType': 'Number',
          },
        ];
      
        return (
          <Form inputList={initialDataPassed} />
        );
      };
      
      const Form = ({ inputList }) => {
        const [formState, setFormState] = useState(createInitialState(inputList));
      
        return (
          <>
            {inputList.map((item) => {
              const handleTextInputValueChange = (text) => {
                // this is solution is better if we base on old value
                setFormState(oldState => ({
                  ...oldState,
                  [item.field]: text
                }))
              };
      
              return <Input key={item.field} value={formState[item.field]} onChangeText={handleTextInputValueChange} fieldType={item.fieldType} />
            })}
          </>
        );
      };
      
      
      const Input = ({value, onChangeText, fieldType}) => {
        const keyboardType = fieldType === 'Number' ? 'numeric' : undefined;
      
        return <TextInput value={value} keyboardType={keyboardType} onChangeText={onChangeText} />
      };
      

      【讨论】:

      • 你能解释一下你的逻辑和步骤吗?
      猜你喜欢
      • 2018-03-23
      • 2014-03-02
      • 2023-03-27
      • 2019-11-22
      • 1970-01-01
      • 1970-01-01
      • 2016-04-23
      • 2020-11-14
      • 2014-11-15
      相关资源
      最近更新 更多