reactjs 在React组件之间访问变量,有没有比将变量作为参数传递更好的方法?

vd2z7a6w  于 2022-11-04  发布在  React
关注(0)|答案(3)|浏览(111)

假设我有一个React组件,类似于:

function App() {
  const [step, setStep] = useState(0);
  const [someValue, setSomeValue] = useState("xyz");
  const var1 = "abc";
  const var2 = "def";

  function StepZero() {
    return <div>
       <p>{someValue}</p>
       <input type="text" id="fname" name="fname" />
       <h1>{var1} {var2}</h1>
       <Button onClick={() => setSomeValue("123")}>Click</Button>
     </div>;
  }

  function StepOne() {
    return <div>
      <h1>{someValue}</h1>
      <Button onClick={() => setSomeValue("456")}>Click</Button>
      <h2>{var1}</h2>
      <h3>{var2}</h3>
    </div>;
  }

  return (
    <div>
        {step === 0 ? (
          <StepZero />
        ) : (
          <StepOne />
        )}
    </div>
  );
}

这里发生的事情是,一旦someValue被设置,整个StepZero被重新呈现,输入丢失。实际上任何用户交互都被重置,例如打开的 accordion 。解决这个问题的方法是将StepZero和StepOne直接放入返回函数,或者将它们放在App组件之外,然后在参数中传递所有变量,如:

{ var1, var2, someValue, setSomeValue }

有没有更好的方法可以将这两个步骤分离成组件,同时仍然能够访问状态和变量/常量,而无需每次状态更改都重新呈现组件,或者不必将所有必需的变量作为参数传递?

  • 请注意,此示例应用程序并不意味着要执行任何功能上有用的操作 *
yvt65v4c

yvt65v4c1#

基于react架构,通过props传递状态和变量是最好的解决方案。
现在,根据你的要求,我有多个建议:

  • 如果常量正在重置,您是否尝试过将常量保存在引用中?(例如:(“abc”);)
  • 如果您不想将数据作为道具传递,但希望它们共享相同的变量,则可以添加Redux(React-redux)或使用ReactContext(How to use React Context
  • 但如果你的项目不大,我建议你把它们当作道具,类似于下面的:

在父App组件中:

const [step, setStep] = useState(0);
  const [someValue, setSomeValue] = useState("xyz");
  const var1 = useRef("abc");
  const var2 = useRef("def");

在一个单独的组件中

function StepZero({someValue,var1,var2,setSomeValue}) {
    return <div>
       <p>{someValue}</p>
       <input type="text" id="fname" name="fname" />
       <h1>{var1.current} {var2.current}</h1>
       <Button onClick={() => setSomeValue("123")}>Click</Button>
     </div>;
  }
tpgth1q7

tpgth1q72#

首先,所有子组件必须位于App函数之外,这样才能拥有自己的状态;其次,您需要将 somevalue 状态传递给props中的所有子组件,并使用回调函数将状态提升到父组件。
https://reactjs.org/docs/lifting-state-up.html
类似于以下内容(我简化了示例的代码)

function StepZero({val,var1,var2,callback}) {
    return <div>
       <p>{val}</p>
       <input type="text" id="fname" name="fname" />
       <h1>{var1} {var2}</h1>
       <Button onClick={() => callback("123")}>Click</Button>
     </div>;
  }

function App() {
  const [step, setStep] = useState(0);
  const [someValue, setSomeValue] = useState("xyz");
  const var1 = "abc";
  const var2 = "def";
  return (
    <div>        
       <StepZero val={someValue} var1={var1} var2={var2} callback={setSomeValue} />        
    </div>
  );
}
mrwjdhj3

mrwjdhj33#

我认为您需要了解更多有关react如何工作的信息,并在此基础上您可以......您需要开始思考的主要思想是react是基于组件的,这意味着“构建管理其自身状态的封装组件”
因此,从这一点上,您可以知道我们有一些组件,它们有一个控件来管理它们状态,因此这将进入下一步..
在第一级,我们有道具、状态和上下文,所有这些概念都将帮助您传递/共享数据
1-道具将用于将数据从较高的组件传递到嵌套的组件,并且其不可变
2-状态将跟踪您的值更改,您可以更新它以更新所需的功能...
3-上下文,它用于在多个组件之间共享数据,而无需将道具从较高的组件传递到较低的组件...
了解这些详细信息后,我们需要进入第二步,了解重新渲染......重新渲染分为初始渲染和重新渲染,初始渲染发生在组件首次出现在屏幕上时,重新渲染发生在React需要使用一些新数据更新应用时,通常根据操作或交互操作进行......注:React处理重新渲染,并知道哪个特定部分正在渲染,并处理重新渲染,其虚拟域,并可以很好地控制...
现在让我们看看您的代码:
1-您可以将详细信息作为道具传递,也可以将App组件拆分为小组件:

function StepZero(props) {
        return <div>
           <p>{props.someValue}</p>
           <input type="text" id="fname" name="fname" />
           <h1>{var1} {var2}</h1>
           <Button onClick={() => props.setSomeValue("123")}>Click</Button>
         </div>;
      }

      function StepOne(props) {
        return <div>
          <h1>{props.someValue}</h1>
          <Button onClick={() => props.setSomeValue("456")}>Click</Button>
          <h2>{var1}</h2>
          <h3>{var2}</h3>
        </div>;
      }

function App() {
      const [step, setStep] = useState(0);
      const [someValue, setSomeValue] = useState("xyz");
      const var1 = "abc";
      const var2 = "def";

      return (
        <div>
            {step === 0 ? (
              <StepZero {youProps}/>
            ) : (
              <StepOne {youProps}/>
            )}
        </div>
      );
    }

第二个解决方案是使用内容React Context
对于重新呈现,您需要正确处理更新依赖关系,如果它在循环或列表中,您需要添加关键字。此外,您必须知道var 1和var 2将保持重新呈现,因为它直接设置而没有状态,ref和它直接放置在组件中,而不是组件外的静态/常量。因此,每次重新渲染组件时,它都会有一个新的内存地址,这意味着任何地方的新重新渲染都已分配给它...

相关问题