11
0

میخوام یه راه درست پیدا کنم که بشه یه سری کامپوننت تعریف کرد که به شکل عمومی استفاده بشن:

<Parent>
  <Child value="1">
  <Child value="2">
</Parent>

یه منطقی بین رندر کردن کامپوننت‌های والد و فرزند وجود داره، مثلاً می‌تونی <select> و <option> رو به عنوان یه مثال از این منطق در نظر بگیری.

اینم یه پیاده‌سازی ساده فقط برای پرسیدن سوال:

var Parent = React.createClass({
  doSomething: function(value) {
  },
  render: function() {
    return (<div>{this.props.children}</div>);
  }
});

var Child = React.createClass({
  onClick: function() {
    this.props.doSomething(this.props.value); // doSomething is undefined
  },
  render: function() {
    return (<div onClick={this.onClick}></div>);
  }
});

سوال اینه که وقتی از {this.props.children} برای تعریف یه کامپوننت رپ استفاده می‌کنی، چجوری می‌تونی یه پراپرتی رو به همه فرزندانش پاس بدی؟

0
پاسخ کاربردی

کلون کردن فرزندان با پراپس‌های جدید

میتونی از React.Children استفاده کنی تا روی فرزندان حلقه بزنی، بعد هر المنت رو با پراپس‌های جدید (که به شکل سطحی مرج میشن) با React.cloneElement کلون کنی.

توی کامنت کد می‌تونی ببینی چرا این روش رو پیشنهاد نمی‌کنم.

const Child = ({ childName, sayHello }) => (
  <button onClick={() => sayHello(childName)}>{childName}</button>
);

function Parent({ children }) {
  // ما تابع رو به المنت‌های فرزند پاس می‌دیم
  function sayHello(childName) {
    console.log(`Hello from ${childName} the child`);
  }

  const childrenWithProps = React.Children.map(children, child => {
    // چک کردن 
    //isValidElement 
    راه مطمئنیه و از خطای تایپ‌اسکریپت هم جلوگیری می‌کنه
    if (React.isValidElement(child)) {
      return React.cloneElement(child, { sayHello });
    }
    return child;
  });

  return <div>{childrenWithProps}</div>
}

function App() {
  // این روش کمتر با تایپ اسکریپت فرندلی هست چون به نظر میاد داری
  //'Child '
  //رو بدون
  //'sayHello'
  //رندر می‌کنی
  return (
    <Parent>
      <Child childName="Billy" />
      <Child childName="Bob" />
    </Parent>
  );
}

ReactDOM.render(<App />, document.getElementById("container"));
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<div id="container"></div>

صدا زدن فرزندان به عنوان یک تابع

به‌طور جایگزین، می‌تونی پراپس‌ها رو به فرزندان از طریق render props پاس بدی. توی این روش، فرزندان (که می‌تونن نام دیگه‌ای هم داشته باشن) یه تابع هستن که می‌تونه آرگومان‌های مورد نظر رو دریافت کنه و فرزندان واقعی رو برگردونه:

const Child = ({ childName, sayHello }) => (
  <button onClick={() => sayHello(childName)}>{childName}</button>
);

function Parent({ children }) {
  function sayHello(childName) {
    console.log(`Hello from ${childName} the child`);
  }

  return <div>{children(sayHello)}</div>
}

function App() {
  return (
    <Parent>
      {(sayHello) => (
        <>
          <Child childName="Billy" sayHello={sayHello} />
          <Child childName="Bob" sayHello={sayHello} />
        </>
      )}
    </Parent>
  );
}

ReactDOM.render(<App />, document.getElementById("container"));
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<div id="container"></div>
ارسال پاسخ به سوال بالا

برای ارسال پاسخ باید وارد اکانتت بشی

اگر پاسخت شامل تکه کدی میشه، از منوی ویرایشگر پایین، تکه کدی که نوشتی رو انتخاب کن و بعد از طریق زبان کدی که نوشتی رو انتخاب کن تا کدت داخل بلاک مخصوص زبان خودش قرار بگیره و کدت خواناتر برای بقیه نشون داده بشه

اگه پاسخت رفرنسی داره، لینک رفرنس رو هم بذار تا پاسختت کاملتر و معتبر تر بشه