මුක්කු {this.props.children to වෙත යොමු කරන්නේ කෙසේද


930

සාමාන්‍ය ආකාරයකින් භාවිතා කළ හැකි සමහර සංරචක අර්ථ දැක්වීමට නිසි ක්‍රමයක් සොයා ගැනීමට මම උත්සාහ කරමි:

<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}එතීමේ අංගයක් නිර්වචනය කිරීමට භාවිතා කරන සෑම අවස්ථාවකම, ඔබ යම් දේපලක් එහි සියලුම දරුවන්ට ලබා දෙන්නේ කෙසේද?


Answers:


999

නව මුක්කු සහිත දරුවන් ක්ලෝන කිරීම

ළමයින්ට ප්‍රතික්‍රියා කිරීමට ඔබට React.Children භාවිතා කළ හැකිය, ඉන්පසු React.cloneElement භාවිතා කර සෑම මූලද්‍රව්‍යයක්ම නව මුක්කු (නොගැඹුරු ඒකාබද්ධ) සමඟ ක්ලෝන කරන්න . උදාහරණයක් වශයෙන්:

const Child = ({ doSomething, value }) => (
    <button onClick={() => doSomething(value)}>Click Me</button>
);

class Parent extends React.Component{
    doSomething = value => {
        console.log("doSomething called by child with value:", value);
    }

    render() {
        const childrenWithProps = React.Children.map(this.props.children, child => {
            // checking isValidElement is the safe way and avoids a typescript error too
            const props = { doSomething };
            if (React.isValidElement(child)) {
                return React.cloneElement(child, props);
            }
            return child;
        });

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

function App() {
    return (
        <Parent>
            <Child value={1} />
            <Child value={2} />
        </Parent>
    );
}

ReactDOM.render(<App />, document.getElementById("container"));

ෆෙඩල්: https://jsfiddle.net/2q294y43/2/

කාර්යයක් ලෙස ළමයින් කැඳවීම

විකල්පයක් ලෙස, ඔබට රෙන්ඩර් මුක්කු සහිත දරුවන්ට මුක්කු යැවිය හැකිය . මෙම ප්‍රවේශයේදී, ළමයින් (එය childrenවෙනත් හෝ වෙනත් මුක්කු නාමයක් විය හැකිය) යනු ඔබට සම්මත කිරීමට අවශ්‍ය ඕනෑම තර්ක පිළිගෙන ළමයින් ආපසු ලබා දිය හැකි ශ්‍රිතයකි:

const Child = ({ doSomething, value }) => (
    <button onClick={() => doSomething(value)}>Click Me</button>
);

class Parent extends React.Component{
    doSomething = value => {
        console.log("doSomething called by child with value:", value);
    }

    render(){
        // note that children is called as a function and we can pass args to it
        return <div>{this.props.children(doSomething)}</div>
    }
};

function App(){
    return (
        <Parent>
            {doSomething => (
                <React.Fragment>
                    <Child doSomething={doSomething} value={1} />
                    <Child doSomething={doSomething} value={2} />
                </React.Fragment>
            )}
        </Parent>
    );
}
 
ReactDOM.render(<App />, document.getElementById("container"));

ඒ වෙනුවට <React.Fragment>හෝ සරලව <>ඔබ කැමති නම් අරාවක් ආපසු ලබා දිය හැකිය.

ෆෙඩල්: https://jsfiddle.net/ferahl/y5pcua68/7/


7
මෙය මට වැඩ කරන්නේ නැත. React.cloneElement ()
පැට්‍රික්

13
මෙම පිළිතුර ක්‍රියා නොකරයි, valueසම්මත වූ දේ doSomethingනැති වී ඇත.
ඩේව්

3
@ ඩොමිනික් ටොබියාස් ආර්ග්, කණගාටුයි, මම අනතුරු ඇඟවීම සඳහා console.log මාරු කළ අතර පරාමිති දෙක එක නූලකට සම්බන්ධ කිරීමට අමතක කළෙමි.
ඩේව්

1
මෙම පිළිතුර සුපිරි ප්‍රයෝජනවත් විය, නමුත් මම මෙහි සඳහන් නොකළ ගැටලුවකට මුහුණ දුන් අතර එය වෙනස් වී ඇති අළුත් දෙයක්ද නැතිනම් එය මගේ අවසානයට අමුතු දෙයක්ද යන්න ගැන මම කල්පනා කළෙමි. මම මගේ ළමා මූලද්‍රව්‍යය ක්ලෝන කරන විට, ක්ලෝනඑලෙමන්ට් හි තුන්වන තර්කයට මම මෙම.ප්‍රොප්ස්.චිල්ඩ්‍රන්.ප්‍රොප්ස්.චිල්ඩ්‍රන් එකතු කරන තෙක් එහි දරුවා පැරණි මූලද්‍රව්‍යයට සකසා ඇත.
aphenine

7
වෙනම මාර්ග පිටුවකින් පටවන ලද මාර්ගයක් (v4) හරහා දරුවා පටවා ඇත්නම් කුමක් කළ යුතුද?
බ්ලාම්බ්

406

එය කිරීමට තරමක් පිරිසිදු ක්‍රමයක් සඳහා, උත්සාහ කරන්න:

<div>
    {React.cloneElement(this.props.children, { loggedIn: this.state.loggedIn })}
</div>

සංස්කරණය කරන්න: ඔබට තනි තනි දරුවන් කිහිප දෙනෙකු සමඟ භාවිතා කිරීමට (දරුවාම අංගයක් විය යුතුය) ඔබට කළ හැකිය. 16.8.6 දී පරීක්ෂා කර ඇත

<div>
    {React.cloneElement(props.children[0], { loggedIn: true, testingTwo: true })}
    {React.cloneElement(props.children[1], { loggedIn: true, testProp: false })}
</div>

10
මම වඩාත්ම ශ්‍රේණිගත පිළිතුර භාවිතා කළෙමි, නමුත් මෙය වඩාත් forward ජුව ඉදිරියට ය! මෙම විසඳුම ඔවුන් ප්‍රතික්‍රියා-රවුටරය උදාහරණ පිටුවේ භාවිතා කරයි.
කැප්ට් ඩේලයිට්

10
මෙය ක්‍රියාත්මක වන ආකාරය (හෝ එය ඇත්ත වශයෙන්ම කරන්නේ කුමක්ද) යමෙකුට පැහැදිලි කළ හැකිද? ලියකියවිලි කියවන විට , මෙය ළමයින් තුළට බැස සෑම දරුවෙකුටම එම මුක්කු එකතු කරන්නේ කෙසේදැයි මට නොපෙනුණි - එය කිරීමට අදහස් කරන්නේ එයද? එය එසේ වන්නේ නම්, මෙය කරන්නේ කුමක්දැයි අප දන්නේ කෙසේද? පාරදෘශ්‍ය දත්ත ව්‍යුහයක් ( this.props.children) වෙත යැවීම පවා වලංගු බව කිසිසේත්ම පැහැදිලි නැත cloneElement... එය ... මූලද්‍රව්‍යයක් අපේක්ෂා කරයි.
GreenAsJade

51
හරියටම, මෙය ළමයින් එකකට වඩා වැඩ කරන බවක් නොපෙනේ.
ඩැනිටා

17
යමෙකු ඔබට එක් දරුවෙකු පමණක් සංරචකයකට ඇතුළත් කරන අතරතුර ක්‍රියා කරන කේතයක් ඔබට ලිවිය හැකිය, නමුත් ඔවුන් තවත් දරුවෙකු එකතු කළ විට එය බිඳ වැටේ ... එය මුහුණත වටිනාකමෙන් එතරම් හොඳ නොවේද? සියලුම ළමයින්ට මුක්කු යැවීම ගැන විශේෂයෙන් විමසූ OP සඳහා එය උගුලක් සේ පෙනේ .
GreenAsJade

10
ඔබේ සංරචකය තනි දරුවෙකු අපේක්ෂා කරන තාක් කල් එහි හරිතය. තනි දරුවෙකු අපේක්ෂා කරන ඔබේ සංරචක propTypes හරහා ඔබට අර්ථ දැක්විය හැකිය. React.Children.onlyශ්‍රිතය එකම දරුවා ආපසු ලබා දෙයි හෝ බහු ගණනක් තිබේ නම් ව්‍යතිරේකයක් විසි කරයි (භාවිත නඩුවක් නොතිබුනේ නම් මෙය නොපවතී).
cchamberlain

82

මේක උත්සාහ කරන්න

<div>{React.cloneElement(this.props.children, {...this.props})}</div>

එය ප්‍රතික්‍රියා -15 භාවිතා කරමින් මට වැඩ කළේය.


3
ටැග් React.cloneElement()වලින් වට නොකර කෙලින්ම ආපසු යා <div>හැකිද? මන්ද, දරුවා <span>(හෝ වෙනත් දෙයක්) නම් සහ එහි ටැග් මූලද්‍රව්‍ය වර්ගය ආරක්ෂා කර ගැනීමට අපට අවශ්‍ය නම් කුමක් කළ යුතුද?
adrianmc

1
එය එක් දරුවෙකු නම් ඔබට එතීම අතහැර දැමිය හැකි අතර මෙම විසඳුම ක්‍රියාත්මක වන්නේ එක් දරුවෙකු සඳහා පමණි.
තාජේ

1
මා වෙනුවෙන් වැඩ කරයි. <div> කොටු නොකර හරි.
බිඳ වැටීම

4
ඔබට ලැබෙන්නේ එක් දරුවෙකු පමණක් බව ඔබට පැහැදිලිවම බලාත්මක කිරීමට අවශ්‍ය නම්, ඔබට එය කළ හැක්කේ React.cloneElement(React.Children.only(this.props.children), {...this.props})එය එක් දරුවෙකුට වඩා සමත් වුවහොත් දෝෂයකි. එවිට ඔබට කොට් .ාශයක් ඔතා අවශ්‍ය නැත.
itsananderson

1
මෙම පිළිතුර මගින් TypeError: චක්‍රීය වස්තු අගය නිපදවිය හැකිය. දරුවාගේ මුක්කු වලින් එකක් වීමට ඔබට අවශ්‍ය let {children, ...acyclicalProps} = this.propsනැතිනම් , භාවිතා කර පසුව භාවිතා කරන්න React.cloneElement(React.Children.only(children), acyclicalProps).
පැරබෝලෝර්ඩ්

72

ළමයින් යොමු කිරීම සඳහා මුක්කු මුර කරන්න.

අනෙක් සියලුම පිළිතුරු බලන්න

සන්දර්භය හරහා සංරචක ගස හරහා බෙදාගත්, ගෝලීය දත්ත සමත් කරන්න

සන්දර්භය සැලසුම් කර ඇත්තේ වර්තමාන සත්‍යාපනය කළ පරිශීලකයා, තේමාව හෝ කැමති භාෂාව වැනි ප්‍රතික්‍රියා සංරචක ගසක් සඳහා “ගෝලීය” ලෙස සැලකිය හැකි දත්ත බෙදා ගැනීමට ය. 1

වියාචනය: මෙය යාවත්කාලීන කළ පිළිතුරකි, පෙර පිළිතුර පැරණි සන්දර්භය API භාවිතා කළේය

එය පාරිභෝගික / සැපයුම් මූලධර්මය මත පදනම් වේ. පළමුව, ඔබේ සන්දර්භය සාදන්න

const { Provider, Consumer } = React.createContext(defaultValue);

ඉන්පසු භාවිතා කරන්න

<Provider value={/* some value */}>
  {children} /* potential consumers */
<Provider />

සහ

<Consumer>
  {value => /* render something based on the context value */}
</Consumer>

සැපයුම්කරුවෙකුගෙන් පැවත එන සියලුම පාරිභෝගිකයින් සැපයුම්කරුගේ අගය මුක්කු වෙනස් වන සෑම විටම නැවත ඉදිරිපත් කරනු ඇත. සැපයුම්කරුගේ සිට එහි පැවත එන පාරිභෝගිකයින් වෙත ප්‍රචාරණය කිරීම අනිවාර්යයෙන්ම යාවත්කාලීන කිරීමේ ක්‍රමයට යටත් නොවේ, එබැවින් මුතුන් මිත්තන්ගේ අංගයක් යාවත්කාලීනයන්ගෙන් ඇප ලබා ගත් විට පවා පාරිභෝගිකයා යාවත්කාලීන වේ. 1

සම්පූර්ණ උදාහරණය, ​​අර්ධ ව්‍යාජ කේතය.

import React from 'react';

const { Provider, Consumer } = React.createContext({ color: 'white' });

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: { color: 'black' },
    };
  }

  render() {
    return (
      <Provider value={this.state.value}>
        <Toolbar />
      </Provider>
    );
  }
}

class Toolbar extends React.Component {
  render() {
    return ( 
      <div>
        <p> Consumer can be arbitrary levels deep </p>
        <Consumer> 
          {value => <p> The toolbar will be in color {value.color} </p>}
        </Consumer>
      </div>
    );
  }
}

1 https://facebook.github.io/react/docs/context.html


7
පිළිගත් පිළිතුර මෙන් නොව, දෙමව්පියන් යටතේ වෙනත් අංග ඇතුළත් වූ විට පවා මෙය නිසියාකාරව ක්‍රියාත්මක වේ. මෙය අනිවාර්යයෙන්ම හොඳම පිළිතුරයි.
සැප්ට්‍රි

6
මුක්කු! = සන්දර්භය
පීටර් පෙලර්

සන්දර්භය හරහා ප්‍රචාරණය වන වෙනස්කම් මත ඔබට රඳා සිටිය නොහැක. මුක්කු වෙනස් විය හැකි විට ඒවා භාවිතා කරන්න.
තාජේ

1
සමහර විට මට නොතේරෙන නමුත් "සන්දර්භය මුක්කු ලබා දෙයි" යැයි පැවසීම වැරදි නොවේද? මා අවසන් වරට සන්දර්භය භාවිතා කළ විට, එය වෙනම දෙයක් (එනම් this.context) - එය සන්දර්භය මුක්කු සමඟ ඉන්ද්‍රජාලිකව ඒකාබද්ධ කළේ නැත. ඔබට හිතාමතාම සන්දර්භය සැකසීමට හා භාවිතා කිරීමට සිදු විය, එය සමස්තයක් වශයෙන් වෙනත් දෙයකි.
ජොෂ්

ඔබ හොඳින් තේරුම් ගත්තා, එය වැරදියි. මම මගේ පිළිතුර සංස්කරණය කර ඇත.
ලියුබොමිර්

50

කැදැලි දරුවන්ට මුක්කු යැවීම

කිරීමට යාවත් කාලීන 16.6 ක්රියාත්මක වෙන්න ඔබ දැන් භාවිතා කළ හැකිය React.createContext හා contextType .

import * as React from 'react';

// React.createContext accepts a defaultValue as the first param
const MyContext = React.createContext(); 

class Parent extends React.Component {
  doSomething = (value) => {
    // Do something here with value
  };

  render() {
    return (
       <MyContext.Provider value={{ doSomething: this.doSomething }}>
         {this.props.children}
       </MyContext.Provider>
    );
  }
}

class Child extends React.Component {
  static contextType = MyContext;

  onClick = () => {
    this.context.doSomething(this.props.value);
  };      

  render() {
    return (
      <div onClick={this.onClick}>{this.props.value}</div>
    );
  }
}


// Example of using Parent and Child

import * as React from 'react';

class SomeComponent extends React.Component {

  render() {
    return (
      <Parent>
        <Child value={1} />
        <Child value={2} />
      </Parent>
    );
  }
}

React.createContext බැබළෙන්නේ React.cloneElement නඩුවට කැදැලි සංරචක හැසිරවිය නොහැකි තැනයි

class SomeComponent extends React.Component {

  render() {
    return (
      <Parent>
        <Child value={1} />
        <SomeOtherComp><Child value={2} /></SomeOtherComp>
      </Parent>
    );
  }
}

3
=> කාර්යයන් නරක පුරුද්දක් වන්නේ මන්දැයි ඔබට පැහැදිලි කළ හැකිද? => ශ්‍රිතය සිදුවීම් හසුරුවන්නන්ට thisසන්දර්භය ලබා ගැනීමට උපකාරී වේ
කෙනත් ට ru ං

EnnKennethTruong එය විදැහුම් කරන සෑම අවස්ථාවකම එය ශ්‍රිතයක් නිර්මාණය කරයි.
itdoesntwork

9
එය සත්‍ය නොවන බව. එය නව ශ්‍රිතයක් නිර්මාණය කරන්නේ පන්තිය නිර්මාණය කළ විට පමණි. විදැහුම්කරණ ක්‍රියාවලියේදී එය නිර්මාණය වී නොමැත ..
කෙනත් ට ru ං

EnnKennethTruong reactjs.org/docs/faq-functions.html#arrow-function-in-render මම සිතුවේ ඔබ විදැහුම්කරණයේ ඊතල ක්‍රියාකාරිත්වය ගැන කතා කරන බවයි.
itdoesntwork

24

ඔබට භාවිතා කළ හැකිය React.cloneElement, ඔබේ යෙදුම තුළ එය භාවිතා කිරීමට පෙර එය ක්‍රියාත්මක වන්නේ කෙසේදැයි දැන ගැනීම වඩා හොඳය. එය හඳුන්වා දී ඇත React v0.13, වැඩි විස්තර සඳහා කියවන්න, එබැවින් මෙම කාර්යය සමඟ ඔබ වෙනුවෙන් යමක්:

<div>{React.cloneElement(this.props.children, {...this.props})}</div>

එබැවින් එය සියල්ල ක්‍රියාත්මක වන්නේ කෙසේද සහ ඔබට ඒවා භාවිතා කළ හැක්කේ කෙසේද යන්න තේරුම් ගැනීමට ප්‍රතික්‍රියා ලේඛනයේ රේඛා ගෙන එන්න:

ප්‍රතික්‍රියා v0.13 RC2 හි දී අපි මෙම අත්සන සමඟ React.addons.cloneWithProps හා සමාන නව API එකක් හඳුන්වා දෙන්නෙමු:

React.cloneElement(element, props, ...children);

ක්ලෝන විත්ප්‍රොප්ස් මෙන් නොව, මෙම නව ශ්‍රිතයට ශෛලිය හා පංතියේ නම ඒකාබද්ධ කිරීම සඳහා කිසිදු ඉන්ද්‍රජාලික හැසිරීමක් නොමැත. එම හේතුව නිසා අපට ට්‍රාන්ස්ෆර්ප්‍රොප්ටෝ වෙතින් එම අංගය නොමැත. මැජික් දේවල් පිළිබඳ සම්පූර්ණ ලැයිස්තුව හරියටම කුමක්දැයි කිසිවෙකුට විශ්වාස නැත, එමඟින් කේතය ගැන තර්ක කිරීම දුෂ්කර වන අතර ශෛලියට වෙනස් අත්සනක් ඇති විට නැවත භාවිතා කිරීමට අපහසු වේ (උදා: එළඹෙන ප්‍රතික්‍රියා ස්වදේශික).

React.cloneElement බොහෝ දුරට සමාන වේ:

<element.type {...element.props} {...props}>{children}</element.type>

කෙසේ වෙතත්, JSX සහ cloneWithProps මෙන් නොව, එය refs ද ආරක්ෂා කරයි. මෙයින් අදහස් කරන්නේ ඔබ එය මත යොමු වූ දරුවෙකු ලබා ගන්නේ නම්, ඔබ එය ඔබේ මුතුන්මිත්තන්ගෙන් අහම්බෙන් සොරකම් නොකරන බවයි. ඔබගේ නව අංගයට අමුණා ඇති එකම ref එක ඔබට ලැබෙනු ඇත.

එක් පොදු රටාවක් නම් ඔබේ දරුවන් සිතියම් ගත කර නව මුක්කු එකතු කිරීමයි. ක්ලෝන විත්ප්‍රොප්ස් වෙත යොමු වීම නැතිවීම පිළිබඳව බොහෝ ගැටලු වාර්තා වූ අතර, ඔබේ කේතය ගැන තර්ක කිරීම දුෂ්කර විය. දැන් ක්ලෝනඑලෙමන්ට් සමඟ එකම රටාව අනුගමනය කිරීම අපේක්ෂිත පරිදි ක්‍රියාත්මක වේ. උදාහරණයක් වශයෙන්:

var newChildren = React.Children.map(this.props.children, function(child) {
  return React.cloneElement(child, { foo: true })
});

සටහන: React.cloneElement (ළමයා, {ref: 'newRef'}) ref එක ඉක්මවා යයි, එබැවින් ඔබ ඇමතුම්-යොමු කිරීම් භාවිතා නොකරන්නේ නම්, දෙමව්පියන් දෙදෙනෙකුට එකම දරුවාට යොමු වීමක් තවමත් කළ නොහැක.

මුක්කු දැන් වෙනස් නොවන බැවින් ප්‍රතික්‍රියා 0.13 වෙත පිවිසීමට මෙය තීරණාත්මක ලක්ෂණයකි. උත්ශ්‍රේණි කිරීමේ මාර්ගය බොහෝ විට මූලද්‍රව්‍යය ක්ලෝන කිරීම වේ, නමුත් එසේ කිරීමෙන් ඔබට ref අහිමි විය හැකිය. එමනිසා, අපට මෙහි වඩා හොඳ වැඩිදියුණු කිරීමේ මාර්ගයක් අවශ්‍ය විය. අපි ෆේස්බුක් හි ඇමතුම් අඩවි යාවත්කාලීන කරමින් සිටියදී අපට මෙම ක්‍රමය අවශ්‍ය බව වැටහුණි. අපට ප්‍රජාවෙන් එකම ප්‍රතිපෝෂණය ලැබුණි. එබැවින් අවසාන නිකුතුවට පෙර තවත් RC එකක් සෑදීමට අපි තීරණය කළෙමු.

අවසානයේදී React.addons.cloneWithProps ඉවත් කිරීමට අපි සැලසුම් කරමු. අපි තවම එය කරන්නේ නැත, නමුත් මෙය ඔබේම භාවිතයන් ගැන සිතීම ආරම්භ කිරීමට හොඳ අවස්ථාවක් වන අතර ඒ වෙනුවට React.cloneElement භාවිතා කිරීම ගැන සලකා බලන්න. අපි එය ඉවත් කිරීමට පෙර ක්ෂය කිරීමේ දැන්වීම් සහිත නිකුතුවක් යැවීමට වග බලා ගන්නෙමු, එබැවින් ක්ෂණික ක්‍රියාමාර්ගයක් අවශ්‍ය නොවේ.

තවත් මෙහි ...


20

දේපල හුවමාරුව සිදු කිරීමට ඔබට ඉඩ සලසන හොඳම ක්‍රමය childrenක්‍රියාකාරී රටාවකට සමානය https://medium.com/merrickchristensen/function-as-child-components-5f3920a9ace9

කේත ස්නිපටය: https://stackblitz.com/edit/react-fcmubc

උදාහරණයක්:

const Parent = ({ children }) => {
    const somePropsHere = {
      style: {
        color: "red"
      }
      // any other props here...
    }
    return children(somePropsHere)
}

const ChildComponent = props => <h1 {...props}>Hello world!</h1>

const App = () => {
  return (
    <Parent>
      {props => (
        <ChildComponent {...props}>
          Bla-bla-bla
        </ChildComponent>
      )}
    </Parent>
  )
}

1
පිළිගත් පිළිතුරට වඩා මෙය මට වඩා සරල බව පෙනේ (සහ කාර්ය සාධනය සඳහා වඩා හොඳද?).
ෂිකියෝ

2
මේ සඳහා ළමයින්ට ශ්‍රිතයක් අවශ්‍ය වන අතර කැදැලි සංරචක සඳහා ක්‍රියා නොකරයි
ඩිජිටල් මායාව

igdigitalillusion, එහි තේරුම කුමක්දැයි මට තේරෙන්නේ නැත nested components. ප්‍රතික්‍රියා වල කූඩු රටා නොමැත, සංයුති පමණි. ඔව්, ළමයින් ශ්‍රිතයක් විය යුතුය, කිසිදු ගැටුම් නොමැත, මන්ද මෙය වලංගු JSX දරුවා ය. ඔබට උදාහරණයක් දිය හැකිද nesting components?
නික් ඕව්චිනිකොව්

1
ගැඹුරින් කැදැලි ඇති දරුවන්ගේ <Parent>{props => <Nest><ChildComponent /></Nest>}</Parent>තත්වය (වැඩ නොකිරීම) වෙනුවට හැසිරවිය හැකි බව ඔබ නිවැරදිය. <Parent><Nest>{props => <ChildComponent />}</Nest></Parent>එබැවින් මෙය හොඳම පිළිතුර බව මම එකඟ වෙමි
ඩිජිටල් මායාව

උත්සාහ කරන විට, මට පහත සඳහන් දේ ලැබේ:TypeError: children is not a function
රයන් ප්‍රෙන්ටිස්

7

පෙළ නූල් වැනි සංරචක ප්‍රතික්‍රියා නොකරන දරුවන් ලැබීම පිළිබඳ ප්‍රශ්නයට කිසිදු පිළිතුරක් ආමන්ත්‍රණය නොකරයි . වැඩ කිරීම මේ වගේ දෙයක් විය හැකිය:

// Render method of Parent component
render(){
    let props = {
        setAlert : () => {alert("It works")}
    };
    let childrenWithProps = React.Children.map( this.props.children, function(child) {
        if (React.isValidElement(child)){
            return React.cloneElement(child, props);
        }
          return child;
      });
    return <div>{childrenWithProps}</div>

}

6

මම එය භාවිතා වැඩ කිරීමට ඉහත පිළිගත් පිළිතුර විසින් අදාල කරුණ නිවැරදි කිරීමට අවශ්ය බව වෙනුවට මෙම පහිටුම් දක්වනය. මෙය සිතියම් ශ්‍රිතයේ විෂය පථය තුළ doSomething ශ්‍රිතය අර්ථ දක්වා නොමැත.

var Parent = React.createClass({
doSomething: function() {
    console.log('doSomething!');
},

render: function() {
    var that = this;
    var childrenWithProps = React.Children.map(this.props.children, function(child) {
        return React.cloneElement(child, { doSomething: that.doSomething });
    });

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

යාවත්කාලීන කිරීම: මෙම විසඳුම ECMAScript 5 සඳහා වන අතර, ES6 හි var හි අවශ්‍යතාවයක් නොමැත = මෙය


13
හෝ භාවිතා කරන්නbind()
plus-

1
හෝ ඊතල ශ්‍රිතයක් ශබ්දකෝෂ විෂය පථයට සම්බන්ධ කරන විට, මම මගේ පිළිතුර යාවත්කාලීන කළෙමි
ඩොමිනික්

දරුවා doSomethingවැනි doSomething: function(obj) { console.log(obj) }හා යම් වස්තුවක් රැගෙන ගියහොත් ඔබ this.props.doSomething(obj)ඉවත් වීමට කැඳවනු ඇත"obj"
conor909

4
@ plus- මම දන්නවා මෙය පැරණි බව, නමුත් මෙහි බන්ධනය භාවිතා කිරීම භයානක අදහසක්, බන්ධනය මඟින් සන්දර්භයක් නව එකක් සමඟ බැඳ තබන නව ශ්‍රිතයක් නිර්මාණය කරයි. මූලික වශයෙන් applyක්‍රමය කැඳවන ශ්‍රිතයකි . bind()විදැහුම්කරණ ක්‍රියාවලියේදී භාවිතා කිරීමෙන් විදැහුම් ක්‍රමය හැඳින්වෙන සෑම අවස්ථාවකම නව ශ්‍රිතයක් නිර්මාණය වේ.
බමී

6

දරුවන් එකක් හෝ වැඩි ගණනක් සලකා බැලීමේ පිරිසිදු ක්‍රමය

<div>
   { React.Children.map(this.props.children, child => React.cloneElement(child, {...this.props}))}
</div>

මෙය මට වැඩ කරන්නේ නැත, එය දෝෂයක් ලබා දෙයි: ළමයින් අර්ථ දක්වා නැත.
Deelux

ළමයින් වෙනුවට ඩීලක්ස් this.props.children
මාටින් ඩෝසන්

මෙය දරුවා තමන්ගේම දරුවන් ලෙස සමත් වේ this.props. පොදුවේ මම නිර්දේශ කරන්නේ ක්ලෝන කිරීම විශේෂිත මුක්කු වලින් මිස සමස්ත ෂෙබාං වලින් නොවේ.
ඇන්ඩි

සමත් {...this.props}වීම මට ප්‍රයෝජනවත් නොවීය, මාර්ගය {...child.props}නිවැරදිද?
ෆෙලිපේ ඔගස්ටෝ

ක්‍රියාකාරී සංරචක සඳහා:React.Children.map(children, child => React.cloneElement(child, props))
vsync

6

ඔබට තවදුරටත් අවශ්‍ය නොවේ {this.props.children}. දැන් ඔබ භාවිතා ඔබේ දරුවා අංගයක් ආවරණය කරනවා හැක renderදී Routeසුපුරුදු පරිදි ඔබගේ මුක්කු සමත්:

<BrowserRouter>
  <div>
    <ul>
      <li><Link to="/">Home</Link></li>
      <li><Link to="/posts">Posts</Link></li>
      <li><Link to="/about">About</Link></li>
    </ul>

    <hr/>

    <Route path="/" exact component={Home} />
    <Route path="/posts" render={() => (
      <Posts
        value1={1}
        value2={2}
        data={this.state.data}
      />
    )} />
    <Route path="/about" component={About} />
  </div>
</BrowserRouter>

2
විදැහුම් මුක්කු දැන් ප්‍රතික්‍රියා ( standardjs.org/docs/render-props.html ) හි සම්මත වන අතර මෙම ප්‍රශ්නයට නව පිළිගත් පිළිතුරක් ලෙස සලකා බැලීම වටී.
ඉයන් ඩන්ෆෝර්ත්

20
මෙය ප්‍රශ්නයට පිළිතුරක් වන්නේ කෙසේද?
මැක්සිමෝ ඩොමින්ගුස්

ඔව් ... මෙය ප්‍රශ්නයට පිළිතුරු නොදෙන්නේ ප්‍රශ්නය ප්‍රතික්‍රියා-රවුටරය ගැන නොවන බැවිනි. කෙසේ වෙතත්, ප්‍රතික්‍රියා-රවුටරයට විශේෂිත වූ මෙම ප්‍රශ්නයට අදාළ මගේ ප්‍රශ්නයට එය පිළිතුරු සපයයි. මෙම මූලික තොරතුරු මට සොයා ගත හැකි ප්‍රතික්‍රියා-රවුටරයේ වෙබ් අඩවියේ කොතැනකවත් පැහැදිලි නැත. ඔවුන්ගේ උත්ශ්‍රේණිගත සටහන් වල නිසැකවම සඳහන් නොවේ (ඒවා දරුණු ලෙස අසම්පූර්ණයි). මෙම පිළිතුර තමන්ගේම ප්‍රශ්නයකට ගෙන යා යුතුය.
juanitogan

4

Parent.jsx:

import React from 'react';

const doSomething = value => {};

const Parent = props => (
  <div>
    {
      !props || !props.children 
        ? <div>Loading... (required at least one child)</div>
        : !props.children.length 
            ? <props.children.type {...props.children.props} doSomething={doSomething} {...props}>{props.children}</props.children.type>
            : props.children.map((child, key) => 
              React.cloneElement(child, {...props, key, doSomething}))
    }
  </div>
);

Child.jsx:

import React from 'react';

/* but better import doSomething right here,
   or use some flux store (for example redux library) */
export default ({ doSomething, value }) => (
  <div onClick={() => doSomething(value)}/>
);

සහ main.jsx:

import React from 'react';
import { render } from 'react-dom';
import Parent from './Parent';
import Child from './Child';

render(
  <Parent>
    <Child/>
    <Child value='1'/>
    <Child value='2'/>
  </Parent>,
  document.getElementById('...')
);

උදාහරණය මෙතැනින් බලන්න: https://plnkr.co/edit/jJHQECrKRrtKlKYRpIWl?p=preview


4

සමහර විට ඔබට මෙම අංගය ප්‍රයෝජනවත් විය හැකිය, බොහෝ අය මෙය ප්‍රති-රටාවක් ලෙස සලකනු ලැබුවද, ඔබ කරන්නේ කුමක්දැයි ඔබ දන්නේ නම් සහ ඔබේ විසඳුම හොඳින් සැලසුම් කරන්නේ නම් එය තවමත් භාවිතා කළ හැකිය.

ළමා සංරචක ලෙස ක්රියා කිරීම


මෙය ප්‍රති-රටාවක් නොවේ: youtube.com/watch?v=BcVAq3YFiuc
Pietro Coelho

4

ඔබට මුක්කු යැවීමට අවශ්‍ය දරුවන් කිහිප දෙනෙකු සිටී නම් , ඔබට එය මේ ආකාරයෙන් කළ හැකිය, React.Children.map:

render() {
    let updatedChildren = React.Children.map(this.props.children,
        (child) => {
            return React.cloneElement(child, { newProp: newProp });
        });

    return (
        <div>
            { updatedChildren }
        </div>
    );
}

ඔබේ සංරචකයට ඇත්තේ එක් දරුවෙකු පමණක් නම්, සිතියම් ගත කිරීමේ අවශ්‍යතාවයක් නොමැත, ඔබට එකවරම ක්ලෝන කළ හැකිය:

render() {
    return (
        <div>
            {
                React.cloneElement(this.props.children, {
                    newProp: newProp
                })
            }
        </div>
    );
}

3

හි ලේඛනවලට අනුව cloneElement()

React.cloneElement(
  element,
  [props],
  [...children]
)

ආරම්භක ස්ථානය ලෙස මූලද්‍රව්‍යය භාවිතා කර නව ප්‍රතික්‍රියා මූලද්‍රව්‍යයක් ක්ලෝන කර ආපසු එවන්න. එහි ප්‍රති ing ලයක් ලෙස මූලද්‍රව්‍යයේ මුක්කු නොගැඹුරු ලෙස ඒකාබද්ධ වන නව මුක්කු ඇත. නව දරුවන් දැනට සිටින දරුවන් වෙනුවට ආදේශ කරනු ඇත. මුල් මූලද්‍රව්‍යයේ යතුර සහ ref සංරක්ෂණය කෙරේ.

React.cloneElement() බොහෝ දුරට සමාන වේ:

<element.type {...element.props} {...props}>{children}</element.type>

කෙසේ වෙතත්, එය refs ද ආරක්ෂා කරයි. මෙයින් අදහස් කරන්නේ ඔබ එය මත යොමු වූ දරුවෙකු ලබා ගන්නේ නම්, ඔබ එය ඔබේ මුතුන්මිත්තන්ගෙන් අහම්බෙන් සොරකම් නොකරන බවයි. ඔබගේ නව අංගයට අමුණා ඇති එකම ref එක ඔබට ලැබෙනු ඇත.

එබැවින් ළමයින්ට අභිරුචි මුක්කු ලබා දීමට ඔබ භාවිතා කරන්නේ ක්ලෝනඑලෙමන්ට් ය. කෙසේ වෙතත්, සංරචකයේ ළමුන් කිහිප දෙනෙකු සිටිය හැකි අතර ඔබට එය ඉක්මවා යා යුතුය. වෙනත් පිළිතුරු යෝජනා කරන්නේ ඔබට ඒවා භාවිතයෙන් සිතියම් ගත කිරීමයි React.Children.map. කෙසේ වෙතත් වෙනස්වීම් React.Children.mapමෙන් නොව React.cloneElementමූලද්‍රව්‍යයේ යතුරු එකතු වන .$අතර උපසර්ගය ලෙස අමතර වේ. වැඩි විස්තර සඳහා මෙම ප්‍රශ්නය පරීක්ෂා කරන්න: React.Children.map තුළ React.cloneElement මූලද්‍රව්‍ය යතුරු වෙනස් කිරීමට හේතු වේ

ඔබට එය වළක්වා ගැනීමට අවශ්‍ය නම්, ඒ වෙනුවට ඔබ forEachවැනි ශ්‍රිතයට යා යුතුය

render() {
    const newElements = [];
    React.Children.forEach(this.props.children, 
              child => newElements.push(
                 React.cloneElement(
                   child, 
                   {...this.props, ...customProps}
                )
              )
    )
    return (
        <div>{newElements}</div>
    )

}

3

ක්රමය 1 - ළමයින් ක්ලෝන කරන්න

const Parent = (props) => {
   const attributeToAddOrReplace= "Some Value"
   const childrenWithAdjustedProps = React.Children.map(props.children, child =>
      React.cloneElement(child, { attributeToAddOrReplace})
   );

   return <div>{childrenWithAdjustedProps }</div>
}

ක්රමය 2 - සංයුක්ත සන්දර්භය භාවිතා කරන්න

සන්දර්භය මඟින් ගැඹුරු ළමා සංරචකයකට මුක්කු යවා එය අතර ඇති සංරචක හරහා මුක්කු ලෙස පැහැදිළිවම යොමු නොකරයි.

සන්දර්භය අඩුපාඩු සමඟ පැමිණේ:

  1. දත්ත විධිමත්ව ගලා එන්නේ නැත - මුක්කු හරහා.
  2. සන්දර්භය භාවිතා කිරීම පාරිභෝගිකයා සහ සැපයුම්කරු අතර ගිවිසුමක් ඇති කරයි. සංරචකයක් නැවත භාවිතා කිරීම සඳහා අවශ්‍ය වන අවශ්‍යතා තේරුම් ගැනීම සහ අනුකරණය කිරීම වඩා දුෂ්කර විය හැකිය.

සංයුක්ත සන්දර්භයක් භාවිතා කිරීම

export const Context = createContext<any>(null);

export const ComposableContext = ({ children, ...otherProps }:{children:ReactNode, [x:string]:any}) => {
    const context = useContext(Context)
    return(
      <Context.Provider {...context} value={{...context, ...otherProps}}>{children}</Context.Provider>
    );
}

function App() {
  return (
      <Provider1>
            <Provider2> 
                <Displayer />
            </Provider2>
      </Provider1>
  );
}

const Provider1 =({children}:{children:ReactNode}) => (
    <ComposableContext greeting="Hello">{children}</ComposableContext>
)

const Provider2 =({children}:{children:ReactNode}) => (
    <ComposableContext name="world">{children}</ComposableContext>
)

const Displayer = () => {
  const context = useContext(Context);
  return <div>{context.greeting}, {context.name}</div>;
};

ටිකක් පරක්කුයි, නමුත් ඔබට අංකනය පැහැදිලි කළ {children}:{children:ReactNode}හැකිද?
කැමීල්

am කැමිල්, එය යතුරු ලියනයකි. දැන් එය දෙස බලන විට, මම ජාවාස්ක්‍රිප්ට් සමඟ පිළිතුරු දෙන්නෙමි, මම යතුරු ලියනය ලිවුවද, මම එය වෙනස් ආකාරයකින් කරන්නෙමි. අනාගතයේදී එය සංස්කරණය කළ හැකිය.
බෙන් කාප්

1
am කැමිල්, මූලික වශයෙන් එයින් අදහස් කරන්නේ යතුර "children"ඇති අගය වර්ගයයිReactNode
බෙන් කාප්

2

@And_rest පිළිතුරට අමතරව, මම ළමයින් ක්ලෝන කර පන්තියක් එක් කරන්නේ එලෙසයි.

<div className="parent">
    {React.Children.map(this.props.children, child => React.cloneElement(child, {className:'child'}))}
</div>

2

මෙම තත්වය හැසිරවීමට සුදුසුම ක්‍රමය රෙන්ඩර් මුක්කු යැයි මම සිතමි

මේ වගේ දෙයක් දෙස බැලීමට දෙමාපිය කේතය ප්‍රතිනිර්මාණය කිරීමෙන් ළමා සංරචකයේ භාවිතා කිරීමට අවශ්‍ය මුක්කු ලබා දීමට ඔබ දෙමාපියන්ට ඉඩ දී ඇත:

const Parent = ({children}) => {
  const doSomething(value) => {}

  return children({ doSomething })
}

එවිට ළමා සංරචකය තුළ ඔබට දෙමව්පියන් විසින් සපයනු ලබන ශ්‍රිතයට ප්‍රවේශ විය හැකිය:

class Child extends React {

  onClick() => { this.props.doSomething }

  render() { 
    return (<div onClick={this.onClick}></div>);
  }

}

දැන් පෙම්වතාගේ ව්‍යුහය මේ ආකාරයෙන් පෙනෙනු ඇත:

<Parent>
  {(doSomething) =>
   (<Fragment>
     <Child value="1" doSomething={doSomething}>
     <Child value="2" doSomething={doSomething}>
    <Fragment />
   )}
</Parent>

දෙමව්පියන් වෙනත් ළමයින් සඳහා වන පෙළක් වන {ළමයින්} සඳහා එතුම පමණක් නම් කුමක් කළ යුතුද?
ඇඩෙබයෝ

2

ක්‍රියාකාරී සංරචක භාවිතා කරන විට, TypeError: Cannot add property myNewProp, object is not extensibleනව ගුණාංග සැකසීමට උත්සාහ කිරීමේදී ඔබට බොහෝ විට දෝෂය ලැබෙනු ඇත props.children. මුක්කු ක්ලෝන කිරීමෙන් පසුව නව මුක්කු වලින් දරුවා ක්ලෝන කිරීමෙන් මේ සඳහා වැඩක් තිබේ.

const MyParentComponent = (props) => {
  return (
    <div className='whatever'>
      {props.children.map((child) => {
        const newProps = { ...child.props }
        // set new props here on newProps
        newProps.myNewProp = 'something'
        const preparedChild = { ...child, props: newProps }
        return preparedChild
      })}
    </div>
  )
}

1

මෙය කළ හැකි සරලම ක්‍රමය:

    {React.cloneElement(this.props.children, this.props)}

5
මෙය මෙම.ප්‍රොප්ස් ළමයින් මෙම දරුවාගේ දරුවන් වෙත පිටපත් නොකරන්නේද? සහ ඇත්ත වශයෙන්ම දරුවා තමා තුළට පිටපත් කිරීම;
අර්ෂාබ් අගර්වාල්

1

තනි ළමා අංගයක් ඇති ඕනෑම කෙනෙකුට මෙය කළ යුතුය.

{React.isValidElement(this.props.children)
                  ? React.cloneElement(this.props.children, {
                      ...prop_you_want_to_pass
                    })
                  : null}

0

ඔබට අවශ්‍ය වන්නේ මෙයද?

var Parent = React.createClass({
  doSomething: function(value) {
  }
  render: function() {
    return  <div>
              <Child doSome={this.doSomething} />
            </div>
  }
})

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

4
නෑ, මගේ එතුමෙහි අන්තර්ගතය යම් නිශ්චිත අන්තර්ගතයකට සීමා කිරීමට මට අවශ්‍ය නැත.
plus-

0

React.children මා වෙනුවෙන් වැඩ නොකිරීමට යම් හේතුවක්. මට වැඩ කළේ මෙයයි.

මට අවශ්‍ය වූයේ දරුවාට පන්තියක් එක් කිරීමට ය. මුක්කු වෙනස් කිරීමට සමානයි

 var newChildren = this.props.children.map((child) => {
 const className = "MenuTooltip-item " + child.props.className;
    return React.cloneElement(child, { className });
 });

 return <div>{newChildren}</div>;

මෙහි උපක්‍රමය වන්නේ React.cloneElement ය . ඔබට ඕනෑම මුක්කු සමාන ආකාරයකින් සමත් විය හැකිය


0

රෙන්ඩර් මුක්කු යනු මෙම ගැටලුවට වඩාත් නිවැරදි ප්‍රවේශයයි. ළමයින්ගේ මුක්කු ලෙස ළමා සංරචකය මව් සංරචකයට යැවීම වෙනුවට, දෙමව්පියන් විසින් ළමා සංරචකය අතින් ඉදිරිපත් කිරීමට ඉඩ දෙන්න. Render යනු ප්‍රතික්‍රියා පරාමිතීන් වන අතර එය ක්‍රියාකාරී පරාමිතිය ගනී. මෙම ශ්‍රිතයේ දී ඔබට අභිරුචි පරාමිතීන් සමඟ ඔබට අවශ්‍ය ඕනෑම දෙයක් ඉදිරිපත් කිරීමට මව් සංරචකයට ඉඩ දිය හැකිය. මූලික වශයෙන් එය ළමා මුක්කු මෙන් ම කරන නමුත් එය වඩාත් අභිරුචිකරණය කළ හැකිය.

class Child extends React.Component {
  render() {
    return <div className="Child">
      Child
      <p onClick={this.props.doSomething}>Click me</p>
           {this.props.a}
    </div>;
  }
}

class Parent extends React.Component {
  doSomething(){
   alert("Parent talks"); 
  }

  render() {
    return <div className="Parent">
      Parent
      {this.props.render({
        anythingToPassChildren:1, 
        doSomething: this.doSomething})}
    </div>;
  }
}

class Application extends React.Component {
  render() {
    return <div>
      <Parent render={
          props => <Child {...props} />
        }/>
    </div>;
  }
}

කෝඩපන් හි උදාහරණය


0

මම මෙම තනතුරට පැමිණියේ ඒ හා සමාන අවශ්‍යතාවයක් සඳහා පර්යේෂණ කරන අතරතුරය, නමුත් මට දැනුනේ ක්ලෝනකරණ විසඳුමක් එතරම් ජනප්‍රිය වී ඇති බවත්, එය අමු විය යුතු බවත්, මගේ අවධානය ක්‍රියාකාරීත්වයෙන් ඉවතට ගන්නා බවත්ය.

ප්‍රතික්‍රියා ලේඛනයේ ඉහළ ඇණවුම් සංරචකවල ලිපියක් මට හමු විය

මෙන්න මගේ නියැදිය:

import React from 'react';

const withForm = (ViewComponent) => {
    return (props) => {

        const myParam = "Custom param";

        return (
            <>
                <div style={{border:"2px solid black", margin:"10px"}}>
                    <div>this is poc form</div>
                    <div>
                        <ViewComponent myParam={myParam} {...props}></ViewComponent>
                    </div>
                </div>
            </>
        )
    }
}

export default withForm;


const pocQuickView = (props) => {
    return (
        <div style={{border:"1px solid grey"}}>
            <div>this is poc quick view and it is meant to show when mouse hovers over a link</div>
        </div>
    )
}

export default withForm(pocQuickView);

උසස් ඇණවුම් සංරචක රටාව ක්‍රියාත්මක කිරීමේදී නම්යශීලී විසඳුමක් මට හමු විය.

ඇත්ත වශයෙන්ම එය ක්‍රියාකාරීත්වය මත රඳා පවතී, නමුත් වෙනත් අයෙකු සමාන අවශ්‍යතාවයක් සොයන්නේ නම් එය හොඳයි, ක්ලෝනකරණය වැනි අමු මට්ටමේ ප්‍රතික්‍රියා කේතය මත යැපීමට වඩා එය හොඳය.

මම සක්‍රියව භාවිතා කරන අනෙක් රටාව වන්නේ බහාලුම් රටාවයි. ඒ ගැන කියවන්න, එහි බොහෝ ලිපි තිබේ.


0

ඉහත සියලු පිළිතුරු වලින් ආශ්වාදයක් ලබා ඇති අතර මෙය මා විසින් කර ඇත. මම සමහර දත්ත, සහ සමහර සංරචක වැනි මුක්කු පසු කරමි.

import React from "react";

const Parent = ({ children }) => {
  const { setCheckoutData } = actions.shop;
  const { Input, FieldError } = libraries.theme.components.forms;

  const onSubmit = (data) => {
    setCheckoutData(data);
  };

  const childrenWithProps = React.Children.map(
    children,
    (child) =>
      React.cloneElement(child, {
        Input: Input,
        FieldError: FieldError,
        onSubmit: onSubmit,
      })
  );

  return <>{childrenWithProps}</>;
};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.