【问题标题】:React - Predicate functional componentReact - 谓词功能组件
【发布时间】:2020-10-02 11:47:49
【问题描述】:

我创建了一个 react 功能组件来基于谓词包装代码段(而不是在 JSX 中使用三元)。

所以,组件看起来像这样:

const PredicateWrapper = ({ children, iff, otherwise }) => (
    iff ? children : (otherwise || null)
);

并且可以这样使用:

<PredicateWrapper iff={students}>
   {students.map(student => <Student />)}
</PredicateWrapper>

问题在于,如果students 为空,则会引发错误“无法读取空属性映射”。如果我用一些文本替换students.map,则文本不会呈现,证明包装器正在工作,但是,包装器的重点是处理students 为空的情况,我希望它不会“在包装器中输入”。

如果iff 是假的,我怎样才能实现这样的东西,允许内部代码不评估并抛出运行时错误?

【问题讨论】:

    标签: reactjs jsx conditional-operator


    【解决方案1】:

    非常有趣的问题!

    我在这里可能大错特错,但我认为这是因为students.map(student =&gt; &lt;Student /&gt; 仍然是您父组件渲染树的一部分。因此,当 React 尝试构建父组件的树时,它会尝试执行引发错误的那一行。

    PredicateWrapper 在子组件被递归时被挂载和解析,这是iff 将启动的时候——但那是在第二次迭代中。

    例如,如果我这样做,我不会得到错误

    const Child = ({ students }) => {
      return students.map(student => <Student />);
    };
    
    
    <PredicateWrapper iff={students}>
      <Child students={students} />
    </PredicateWrapper>
    

    【讨论】:

      【解决方案2】:

      让我们看看如何将 JSX 编译成带有 online Babel compiler 的 JavaScript:

      const PredicateWrapper = ({ children, iff, otherwise }) =>
        iff ? children : otherwise || null;
      
      const students = null;
      
      const App = () =>
        React.createElement(
          PredicateWrapper,
          {
            iff: students,
          },
          students.map((student) => React.createElement(Student, null))
        );
      

      现在您可以看到students.map 将被执行并导致错误“Cannot read property map of null”

      实现目标的一种可能实现是使用渲染道具

      术语“render prop”是指一种在 使用值为函数的 prop 对组件进行反应。

      const PredicateWrapper = ({ render, iff, otherwise = () => null }) =>
        iff ? render() : otherwise();
      
      const StudentA = () => <span>?</span>;
      const StudentB = () => <span>?</span>;
      
      const students = [StudentA, StudentB];
      //const students = null;
      
      function App() {
        return (
          <PredicateWrapper
            iff={students}
            render={() => students.map(Student => <Student />)}
          />
        );
      }
      

      【讨论】:

      • 感谢您的解释。不过,我不确定我是否喜欢建议的解决方案,因为渲染内容可能非常大。如果我已经用大括号括起来了,我可以改用三元
      猜你喜欢
      • 1970-01-01
      • 2021-05-13
      • 1970-01-01
      • 2021-08-06
      • 2010-10-07
      • 2019-05-06
      • 2015-07-26
      • 2020-06-13
      • 1970-01-01
      相关资源
      最近更新 更多