React 上有 2 个参考文献的问题

问题描述 投票:0回答:1

我有 1 个

ref
,来自
useForm
-
register

const {register, errors} = useForm<any>({
   reValidateMode: "onChange",
   mode: "onChange",
   nativeValidation: false
});

<CustomTextarea
     register={register({
          required: "This is the required field"
     })}
     errors={errors}
     name="custom_name"
     label="Test label"
     placeholder="Test placeholder" 
     value={customEmails} 
     setDataChanged={handleCustomEmailsChange}
     isBBCode={false}
     isFocus={true}
     rows={4}
/>

和 2 个

ref
来自组件:

import React, {useState, useRef, useEffect} from "react";
import {getInstanceError} from "../../utils/getInstanceError";
import ICustomTextarea from "../../typings/ICustomTextarea";
import CustomTooltip from "../Forms/common/CustomTooltip";

const CustomTextarea = ({register, errors, name, label, isDisabled, defaultValue = "", placeholder = "", isBBCode, isFocus, rows, isCopy, setDataCopiedToClipboard, setDataChanged, ...rest}: ICustomTextarea) => {
    const [touch, setTouch] = useState(false);
    const [textareaValue, setTextareaValue] = useState(defaultValue);
    const textareaRef = useRef<HTMLTextAreaElement | null>(null);
    const {
        getMessageError,
        getClassError
    } = getInstanceError(errors);

    const combinedRef = (element: HTMLTextAreaElement | null) => {
        textareaRef.current = register(element);
    };

    useEffect(() => {
        if (isFocus && textareaRef.current) {
            textareaRef.current.focus();

            if (textareaRef.current.value.length === 0) {
                textareaRef.current.select();
            }
        }

        if (isCopy && textareaRef.current) {
            if (textareaRef.current.value.length > 0) {
                textareaRef.current.select();
                navigator.clipboard.writeText(textareaRef.current.value);
                setDataCopiedToClipboard?.();
            }
        }
    }, [isFocus, isCopy]);

    if (isDisabled) {
        return null;
    }

    const errorMsg = getMessageError(name);
    console.log("errorMsg: ", errorMsg);

    const handelBlur = () => {
        setTouch(true);
        console.log("handelBlur!!!");
    };

    const handleChange = (event) => {
        const data = event.target.value;
        setTextareaValue(data);
        setDataChanged?.(data);
    };

    const handleBBCodeButtonClick = (bbcodeTag) => {
        textareaRef.current?.focus();
        const start = textareaRef.current?.selectionStart;
        const end = textareaRef.current?.selectionEnd;
        const selectedText = textareaValue.substring(start, end);
        const newData = textareaValue.substring(0, start) + `[${bbcodeTag}]${selectedText}[/${bbcodeTag}]` + textareaValue.substring(end);
        setTextareaValue(newData);
        setDataChanged?.(newData);
    };

    return (
      <div className={getClassError(name, touch)}>
        {label && <label>{label}</label>}
        <textarea 
            name={name} 
            placeholder={placeholder}
            value={textareaValue}
            ref={combinedRef}
            onBlur={handelBlur}
            onChange={handleChange}
            rows={rows}
            {...rest}
        />
        {errorMsg && <p>{errorMsg}</p>}
        {isBBCode && 
            <div className="bbcode-container">
                <CustomTooltip msg="Bold"><button className="bbcode-btn" id="bold-btn" type="button" name="codeB" onClick={() => handleBBCodeButtonClick("b")}>B</button></CustomTooltip>
                <CustomTooltip msg="Italic"><button className="bbcode-btn" id="italic-btn" type="button" name="codeI" onClick={() => handleBBCodeButtonClick("i")}>i</button></CustomTooltip>
                <CustomTooltip msg="Underline"><button className="bbcode-btn" id="underline-btn" type="button" name="codeU" onClick={() => handleBBCodeButtonClick("u")}>u</button></CustomTooltip>
                <CustomTooltip msg="LineThrough"><button className="bbcode-btn" id="linethrough-btn" type="button" name="codeS" onClick={() => handleBBCodeButtonClick("s")}>S</button></CustomTooltip>
                <CustomTooltip msg="Left"><button className="bbcode-btn" id="left-btn" type="button" name="codeL">L</button></CustomTooltip>
                <CustomTooltip msg="Center"><button className="bbcode-btn" id="center-btn" type="button" name="codeC">C</button></CustomTooltip>
                <CustomTooltip msg="Right"><button className="bbcode-btn" id="right-btn" type="button" name="codeR">R</button></CustomTooltip>
                <CustomTooltip msg="Inline"><button className="bbcode-btn" id="inline-btn" type="button" name="codeInline">Inline</button></CustomTooltip>
                <CustomTooltip msg="Image"><button className="bbcode-btn" id="img-btn" type="button" name="codeImg">Image</button></CustomTooltip>
                <CustomTooltip msg="Quote"><button className="bbcode-btn" id="quote-btn" type="button" name="codeQuote">Quote</button></CustomTooltip>
                <CustomTooltip msg="Link"><button className="bbcode-btn" id="url-btn" type="button" name="codeUrl">Link</button></CustomTooltip>
                <CustomTooltip msg="Code"><button className="bbcode-btn" id="code-btn" type="button" name="codeCode">Code</button></CustomTooltip>
                <CustomTooltip msg="Spoiler"><button className="bbcode-btn" id="spoiler-btn" type="button" name="codeSpoiler">Spoiler</button></CustomTooltip>
                <CustomTooltip msg="List"><button className="bbcode-btn" id="list-btn" type="button" name="codeList">List</button></CustomTooltip>
            </div>
        }
      </div>      
    );
};

export default CustomTextarea;

它无法合并这 2 个参考。当我在文本区域中输入一些数据时,它会跳过第一个字符并仅从第二个字符开始写入,或者当我尝试删除它时,它会从第二次尝试中删除。请查看下面的屏幕截图:

有什么想法如何正确组合这两个参考来解决这个问题?

reactjs typescript ref
1个回答
0
投票

我通过删除

register
功能并自行设置文本区域验证解决了这个问题。

代码:

import React, {useState, useRef, useEffect} from "react";
import ICustomTextarea from "../../typings/ICustomTextarea";
import CustomTooltip from "../Forms/common/CustomTooltip";

const CustomTextarea = ({name, label, isDisabled, defaultValue = "", value = "", placeholder = "", isBBCode, isFocus, rows, isCopy, setDataCopiedToClipboard, setDataChanged, isClear, setDataCleared, ...rest}: ICustomTextarea) => {
    const [touch, setTouch] = useState(false);
    const [errorMsg, setErrorMsg] = useState("");
    const textareaRef = useRef<HTMLTextAreaElement | null>(null);

    useEffect(() => {
        if (isFocus && textareaRef.current) {
            textareaRef.current.focus();

            if (textareaRef.current.value.length === 0) {
                textareaRef.current.select();
            }
        }

        if (isCopy && textareaRef.current) {
            if (textareaRef.current.value.length > 0) {
                textareaRef.current.select();
                navigator.clipboard.writeText(textareaRef.current.value);
                setDataCopiedToClipboard?.();
            }
        }

        if (isClear && textareaRef.current) {
            if (textareaRef.current.value.length > 0) {
                textareaRef.current.value = "";
                setDataCleared?.();
            }
        }
    }, [isFocus, isCopy, isClear]);

    if (isDisabled) {
        return null;
    }

    const handelBlur = () => {
        checkTextareaData(textareaRef.current?.value);
    };

    const checkTextareaData = (data) => {
        setTouch(true);
        
        if (data.length === 0) { 
            setErrorMsg("This is the required field");
        } else {
            setErrorMsg("");
        }
    };

    const handleChange = (event) => {
        const data = event.target.value;
        checkTextareaData(data);
        setDataChanged?.(data);
    };

    const handleBBCodeButtonClick = (bbcodeTag, additionalTag = "") => {
        textareaRef.current?.focus();
        const start = textareaRef.current?.selectionStart ?? 0;
        const end = textareaRef.current?.selectionEnd ?? 0;
        const selectedText = textareaRef.current?.value.substring(start, end) ?? "";
        let newData = "";
        
        if (bbcodeTag === "li") {
            newData = `[${bbcodeTag}]` + textareaRef.current?.value.substring(0, start) + selectedText + textareaRef.current?.value.substring(end);
        } else if (additionalTag) {
            newData = textareaRef.current?.value.substring(0, start) + `[${bbcodeTag}=${additionalTag}]` + selectedText + `[/${bbcodeTag}]` + textareaRef.current?.value.substring(end);
        } else {
            newData = textareaRef.current?.value.substring(0, start) + `[${bbcodeTag}]${selectedText}[/${bbcodeTag}]` + textareaRef.current?.value.substring(end);
        }

        checkTextareaData(newData);
        setDataChanged?.(newData);
    };

    return (
      <div className={`${errorMsg && touch ? "form-group form-group-error" : !errorMsg && touch ? "form-group form-group-success" : "form-group"}`}>
        {label && <label>{label}</label>}
        <textarea 
            name={name} 
            placeholder={placeholder}
            defaultValue={defaultValue}
            value={value}
            ref={textareaRef}
            onBlur={handelBlur}
            onChange={handleChange}
            rows={rows}
            {...rest}
        />
        {errorMsg && <p>{errorMsg}</p>}
        {isBBCode && 
            <div className="bbcode-container">
                <CustomTooltip msg="Жирний"><button className="bbcode-btn" id="bold-btn" type="button" name="codeB" onClick={() => handleBBCodeButtonClick("b")}>B</button></CustomTooltip>
                <CustomTooltip msg="Курсив"><button className="bbcode-btn" id="italic-btn" type="button" name="codeI" onClick={() => handleBBCodeButtonClick("i")}>i</button></CustomTooltip>
                <CustomTooltip msg="Підкреслити"><button className="bbcode-btn" id="underline-btn" type="button" name="codeU" onClick={() => handleBBCodeButtonClick("u")}>u</button></CustomTooltip>
                <CustomTooltip msg="Перечеркнути"><button className="bbcode-btn" id="linethrough-btn" type="button" name="codeS" onClick={() => handleBBCodeButtonClick("s")}>S</button></CustomTooltip>
                <CustomTooltip msg="Ліворуч"><button className="bbcode-btn" id="left-btn" type="button" name="codeL" onClick={() => handleBBCodeButtonClick("left")}>L</button></CustomTooltip>
                <CustomTooltip msg="По центру"><button className="bbcode-btn" id="center-btn" type="button" name="codeC" onClick={() => handleBBCodeButtonClick("center")}>C</button></CustomTooltip>
                <CustomTooltip msg="Праворуч"><button className="bbcode-btn" id="right-btn" type="button" name="codeR" onClick={() => handleBBCodeButtonClick("right")}>R</button></CustomTooltip>
                <CustomTooltip msg="В лінію"><button className="bbcode-btn" id="inline-btn" type="button" name="codeInline" onClick={() => handleBBCodeButtonClick("inline")}>В лінію</button></CustomTooltip>
                <CustomTooltip msg="Зображення"><button className="bbcode-btn" id="img-btn" type="button" name="codeImg" onClick={() => handleBBCodeButtonClick("img", "Заголовок зображення")}>Зображення</button></CustomTooltip>
                <CustomTooltip msg="Цитата"><button className="bbcode-btn" id="quote-btn" type="button" name="codeQuote" onClick={() => handleBBCodeButtonClick("quote")}>Цитата</button></CustomTooltip>
                <CustomTooltip msg="Посилання"><button className="bbcode-btn" id="url-btn" type="button" name="codeUrl" onClick={() => handleBBCodeButtonClick("url", "Посилання")}>Посилання</button></CustomTooltip>
                <CustomTooltip msg="Код"><button className="bbcode-btn" id="code-btn" type="button" name="codeCode" onClick={() => handleBBCodeButtonClick("code")}>Код</button></CustomTooltip>
                <CustomTooltip msg="Спойлер"><button className="bbcode-btn" id="spoiler-btn" type="button" name="codeSpoiler" onClick={() => handleBBCodeButtonClick("spoiler", "Заголовок")}>Спойлер</button></CustomTooltip>
                <CustomTooltip msg="Лист"><button className="bbcode-btn" id="list-btn" type="button" name="codeList" onClick={() => handleBBCodeButtonClick("li")}>Список</button></CustomTooltip>
            </div>
        }
      </div>      
    );
};

export default CustomTextarea;

现在,我初始化 CustomTextarea 组件,而不使用

register & errors
中的
useForm

<CustomTextarea
     name="custom_name"
     label="Test label"
     placeholder="Test placeholder" 
     value={customEmails} 
     setDataChanged={handleCustomEmailsChange}
     isBBCode={false}
     isFocus={true}
     rows={4}
/>

此问题已解决。

© www.soinside.com 2019 - 2024. All rights reserved.