【问题标题】:Limiting keyboard inputs to A-Z as opposed to any keyboard input on React component将键盘输入限制为 A-Z,而不是 React 组件上的任何键盘输入
【发布时间】:2021-08-25 14:21:27
【问题描述】:

我刚刚遇到一个我正在努力解决的组件,但基本上我关心的值是allowForClassification,它是一个布尔值,它被传递到子组件并确定是否不是我们显示一个按钮。 (基本上意味着只有在用户输入了一个字母后才会出现“查找”按钮——目前即使是空格键也会触发该按钮出现)。

但是我很难理解在这个组件中进行检查的确切位置,我知道如果返回 canClassify!classifyInProgress,底部的 allowForClassification 设置为 true 但我找不到在他们检查键盘输入的地方,任何建议都会很有帮助。

const getCcceValues = (object?: FormObjectModel | null) => {
  const ccceInput: $Shape<CcceInput> = {};

  if (!object) {
    return {};
  }

  const ccceValues = object.attributeCollection.questions.reduce(
    (acc, attribute) => {
      const fieldEntry = ccceBeInformedFieldMap.get(attribute.key);

      if (fieldEntry) {
        acc[fieldEntry] = attribute.value;
      }

      return acc;
    },
    ccceInput
  );

  // ready to perfom classification based on user input
  const canClassify = Object.values(ccceValues).every(Boolean);

  return { canClassify, ccceValues };
};

export const useCcceEmbed = (
  ccceResultAttribute: AttributeType,
  onChange: Function
): CcceHook => {
  const { object, form } = useFormObjectContext();
  const [resultCode, setResultCode] = useState<string | null>(null);

  const { canClassify, ccceValues } = getCcceValues(object);

  const { handleSubmit } = useFormSubmit();

  const [showModal, setShowModal] = useState<boolean>(false);

  const handleCloseModal = useCallback(() => setShowModal(false), []);
  const handleShowModal = useCallback(() => setShowModal(true), []);

  // state value to keep track of a current active classification
  const [classifyInProgress, setClassifyInProgress] = useState<boolean>(false);

  const handleResult = useCallback(
    (result) => {
      if (result?.hsCode) {
        onChange(ccceResultAttribute, result.hsCode);

        setResultCode(result.hsCode);
        setClassifyInProgress(false);

        handleSubmit(form);
      }
    },
    [ccceResultAttribute, form, handleSubmit, onChange]
  );

  const handleCancelClassify = useCallback(() => {
    setClassifyInProgress(false);
    handleCloseModal();
  }, [handleCloseModal]);

  const handleClassify = useCallback(
    (event?: SyntheticEvent<any>) => {
      if (event) {
        event.preventDefault();
        console.log("scenario 1");
      }

      if (classifyInProgress || !canClassify) {
        console.log("scenario 2");
        return;
      }

      const ccce = window.ccce;

      if (!ccceValues || !ccce) {
        throw new Error("Unable to classify - no values or not initialised");
        console.log("scenario 3");
      }

      setClassifyInProgress(true);

      const classificationParameters = {
        ...ccceValues,
        ...DEFAULT_EMBED_PROPS,
      };

      ccce.classify(
        classificationParameters,
        handleResult,
        handleCancelClassify
      );
    },
    [
      classifyInProgress,
      canClassify,
      ccceValues,
      handleResult,
      handleCancelClassify,
    ]
  );

  return {
    allowForClassification: canClassify && !classifyInProgress,
    classifyInProgress,
    dataProfileId,
    embedID: EMBED_ID,
    handleCancelClassify,
    handleClassify,
    handleCloseModal,
    handleShowModal,
    isDebugMode,
    resultCode,
    shouldShowModal: showModal,
  };
};

【问题讨论】:

    标签: javascript reactjs keyboard-events setstate


    【解决方案1】:

    解决方案

    此代码中缺少很多内容,可能有更好的方法来做到这一点。但这是我想出的。

    我们可以评估输入值是否包含字符,而不是评估输入值是否为空。

    替换这一行:

    const canClassify = Object.values(ccceValues).every(Boolean);
    

    这两行:

    const regex = new RegExp('\w', 'g');
    
    const canClassify = Object.values(ccceValues).every(value => regex.test(value));
    

    或者这一行:

    const canClassify = Object.values(ccceValues).every(value => /\w/g.test(value))
    

    为什么是那条线?

    我通过逆向工作得出了该解决方案。这是我通过代码到达正确位置所采取的所有步骤。

    allowForClassification: canClassify && !classifyInProgress,
    

    allowForClassificationtrue 如果 canClassifytrue 并且 classifyInProgressfalse。如果我们已经在执行分类,我们不想分类。这就说得通了。所以我们关心的是canClassify 值。

    const { canClassify, ccceValues } = getCcceValues(object);
    

    canClassify来自getCcceValues函数,其值可能取决于object的值。

    const { object, form } = useFormObjectContext();
    

    object 来自某个外部钩子,这对我来说是一条死胡同,因为我看不到该代码。但请注意,可能这里有一些替代解决方案。

    const canClassify = Object.values(ccceValues).every(Boolean);
    

    .every(Boolean) 与写出长格式.every(value =&gt; Boolean(value)) 具有相同的含义。如果ccceValues 的每个值在转换为Boolean 时都是true,则canClassifytrue。这意味着该值不是:false0-00n""nullundefinedNaN。 (source)

    const ccceInput: $Shape<CcceInput> = {};
    
    const ccceValues = object.attributeCollection.questions.reduce(
        (acc, attribute) => {
          const fieldEntry = ccceBeInformedFieldMap.get(attribute.key);
    
          if (fieldEntry) {
            acc[fieldEntry] = attribute.value;
          }
    
          return acc;
        },
        ccceInput
    );
    

    ccceValues 有点复杂。它由array .reduce() 操作创建。它以ccceInput 的初始值开始,它是一个空对象{}。在迭代的每一步,它可能会在该对象上设置一个属性。最终的值是设置了一堆属性后的对象。

    回调中的参数是acc——我们正在构建的对象,attribute——questions 数组的当前元素。我们设置的键是fieldEntry,值是attribute.value

    请记住,canClassify 检查是否所有 都是“真实的”。所以关键不重要。我们只关心价值 (attribute.value)。


    为什么是那个代码?

    但是向后工作,我们学到的是,当 canClassify/allowForClassifiationtrue 在您希望它是 false 的情况下,这是因为有些值 Boolean(attribute.value) 是 @ 987654376@ 当你希望它是 false。这是为什么呢?

    我将做出一个合乎逻辑的假设,即attribute.value 变量包含用户在框中键入的字符串。

    请记住我之前所说的关于Boolean 铸造的内容。空字符串''false,所有其他字符串为true。因此,如果object.attributeCollection.questions 中至少有一个框用户没有输入任何内容,那么allowForClassification 将是false,因为attribute.value 将是''

    只要用户点击最后一个框中的空格键,attribute.value 就会变成' '这个字符串的Boolean 值为true,所以allowForClassification 现在是true

    但您想应用不同的规则集。当且仅当它包含至少一个字母时,您希望将值视为true。我们可以使用简单的regular expression 进行检查。我不确定您的确切规则集(数字可以吗?下划线呢?重音/非拉丁字符呢?),因此您可能需要调整正则表达式。但这应该可以让您完成 99% 的目标。

    const regex = new RegExp('\w', 'g');
    // can also be written as: const regex = /\w/g;
    

    我正在使用 \w 字母数字 character classg 全局匹配 flag 来匹配字符串中任何位置的任何字母数字字符。

    要检查字符串是否匹配此正则表达式,请使用.test() 方法。

    const hasCharacter = regex.test(someString);
    

    我们想在canClassify.every() 回调中使用这个函数,而不是Boolean 构造函数。所以我们写:

    const canClassify = Object.values(ccceValues).every(value => regex.test(value));
    

    【讨论】:

      猜你喜欢
      • 2013-09-18
      • 2011-11-16
      • 2014-08-14
      • 2016-05-29
      • 2017-10-30
      • 2012-04-01
      • 1970-01-01
      • 2011-06-16
      • 1970-01-01
      相关资源
      最近更新 更多