【问题标题】:React Hooks useRef initialization issue, useRef only works on subsequent callsReact Hooks useRef 初始化问题,useRef 仅适用于后续调用
【发布时间】:2020-12-26 06:24:44
【问题描述】:

我正在将 useRef 实施到我的项目中。我有一个包含可点击部分的表单。单击后,它会打开表单。我正在使用 Reactstrap Collapse 来显示/隐藏表单。我需要能够打开表单并显示需要填写的部分,但是一旦我单击该部分,scrollIntoView 将不起作用,直到我再次打开和关闭表单。我难住了。我console.log(formRef),引用按预期返回我希望在后续调用中滚动到视口顶部的组件。我的猜测是 formRef 被初始化为 null 开始,因此对 ref 的初始调用不起作用。但是,一旦它知道 ref,后续调用就会起作用。我不知道该怎么做..

如果我需要提供一个被剥离的示例,请告诉我。我希望这只是一个初始化问题。

表格

import React, { useRef, useContext, useEffect } from "react";
import {
  FormQuestionsContext,
  FormAnswersContext,
  ExpandedSectionContext,
} from "../../Store";
import SectionHeader from "../SectionHeader";
import ImageUploader from "../CommentsSection";
import Ratings from "../Ratings";
import { Collapse, Button, CardBody, Card } from "reactstrap";
import FontAwesome from "react-fontawesome";
import styles from "./bedthreeform.module.css";

function BedThreeForm({ Name }) {
  const formRef = useRef(null); //useRef Initialization
  const [expandedSection, setExpandedSection] = useContext(
    ExpandedSectionContext
  );
  const [formQuestions, setFormQuestions] = useContext(FormQuestionsContext);
  const [formAnswers, setFormAnswers] = useContext(FormAnswersContext);
  const array = formQuestions.bedthree;
  const onChange = (e, name) => {
    const { value } = e.target;
    setFormAnswers((state) => ({
      ...state,
      [Name]: { ...state[Name], [name]: value },
    }));
  };

  //! The function I use when I want to tell useRef to scrollIntoView
  const handleOpen = () => {
    expandedSection === Name
      ? setExpandedSection("")
      : setExpandedSection(Name);
    formRef.current.scrollIntoView();
  };

  const answeredQuestions = formAnswers.bedthree
    ? Object.keys(formAnswers.bedthree)
    : null;
  console.log(formRef);
  return (
    <div>
      <Button
        className={styles["CollapseBtn"]}
        onClick={handleOpen} //Calling the function here
        style={
          answeredQuestions &&
          answeredQuestions.length === formQuestions.bedthree.length
            ? {
                color: "white",
                ":focus": {
                  backgroundColor: "#02BD43",
                },
                backgroundColor: "#02BD43",
                marginBottom: "1rem",
                width: "100%",
              }
            : answeredQuestions &&
              answeredQuestions.length !== formQuestions.bedthree.length
            ? {
                color: "white",
                ":focus": {
                  backgroundColor: "#bd0202",
                },
                backgroundColor: "#bd0202",
                marginBottom: "1rem",
                width: "100%",
              }
            : {
                ":focus": {
                  backgroundColor: "#fafafa",
                },
                marginBottom: "1rem",
                width: "100%",
              }
        }
      >
        <p>BEDROOM #3 INSPECTION</p>
        <FontAwesome
          className="super-crazy-colors"
          name="angle-up"
          rotate={expandedSection === Name ? null : 180}
          size="lg"
          style={{
            marginTop: "5px",
            textShadow: "0 1px 0 rgba(0, 0, 0, 0.1)",
          }}
        />
      </Button>
      <Collapse
        className={styles["Collapse"]}
        isOpen={expandedSection === Name}
      >
        <Card>
          <CardBody>
            {array ? (
              <div>
                <SectionHeader title="Bedroom #3 Inspection" name={Name} />
                <div
                  ref={formRef}
                  className={styles["BedroomThreeFormWrapper"]}
                  id="bedroom-three-form"
                >
                  {array.map((question, index) => {
                    const selected =
                      formAnswers[Name] && formAnswers[Name][question]
                        ? formAnswers[Name][question]
                        : "";
                    return (
                      <div className={styles["CheckboxWrapper"]} key={index}>
                        <h5>{question}</h5>
                        <Ratings
                          section={Name}
                          question={question}
                          onChange={onChange}
                          selected={selected}
                        />
                      </div>
                    );
                  })}
                </div>
                {!answeredQuestions ? (
                  ""
                ) : (
                  <Button
                    onClick={(e) => e.preventDefault()}
                    style={
                      !answeredQuestions ||
                      (answeredQuestions &&
                        answeredQuestions.length !==
                          formQuestions.bedthree.length)
                        ? {
                            backgroundColor: "#bd0202",
                            color: "white",
                            pointerEvents: "none",
                          }
                        : {
                            backgroundColor: "#02BD43",
                            color: "white",
                            pointerEvents: "none",
                          }
                    }
                  >
                    {!answeredQuestions ||
                    (answeredQuestions &&
                      answeredQuestions.length !==
                        formQuestions.bedthree.length)
                      ? "Incomplete"
                      : "Complete"}
                  </Button>
                )}
                <br />
                <ImageUploader name="bedthree" title={"Bedroom #3"} />
              </div>
            ) : (
              <div></div>
            )}
          </CardBody>
        </Card>
      </Collapse>
    </div>
  );
}

export default BedThreeForm;

CodeSandbox Stripped Form 没有按预期工作,但这是剥离的代码。

更新我愿意接受绕过此操作的建议或替代方法。我不确定为什么它只在后续调用中才会这样做。

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    看看这些行:

             <CardBody>
                {array ? (
                    ...
                    <div
                      ref={formRef}
                      ...
    

    只有在定义了array 时才会评估这个(虚拟)dom。如果您希望您的 formRef 始终指向 dom,那么您必须将其从您的条件中删除。

    【讨论】:

    • 我把if条件语句取出来,加到外面一个空的div里。但是,我仍然收到相同的输出。
    • 你能把它推送到codesandbox吗?帮助你会容易得多
    • 我现在正在更新,但是无论出于何种原因,codeandbox 都没有正确显示表单。然而,里面是剥离的形式。您可以复制并粘贴到您想要的任何内容。请注意当您单击它时它会改变打开和关闭的方式。
    • 查看日志,reactstrap 有很多错误
    • 我想通了。我刚刚发布了答案。干杯。
    【解决方案2】:

    我已经找到问题了,问题是当折叠中的内容尚未加载时调用它,Reactstrap 有一个属性onEntered 基本上设置后,将在折叠时立即运行该函数已完全打开。我找到的例子是here。此外,通过在 Reactstrap 组件上设置属性 innerRef,我可以像使用 ref 处理常规组件一样操作它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-18
      • 1970-01-01
      • 1970-01-01
      • 2022-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多