1
  1. <ComponentA> is supposed to render <ComponentB> (not import it but rather render it as a child)
  2. <ComponentB> comes with its own props (propsForComponentB)
  3. But I want <ComponentA> to pass one extra prop of its own to <ComponentB>

I'm thinking of something like the below, but being new to React I don't know if/how it's possible:

  <ComponentA>
    <ComponentB {...propsForComponentB} />
  </ComponentA>
//component-a.jsx

export default function(props) {

  function doSomething(dataFromChildComponent){
     ...
  }

  return(
    {
      /* 
        Here I want to render the children components while passing an extra prop
        to each of them. My syntax is obviously wrong. This is mostly pseudocode to get 
        my point across. Is this possible in some way ? 
      */ 
      props.children.map((child) => {child componentAmethod={doSomething}  }) 
    }
  )
}
//component-b.jsx

export default function(props) {
  /*
     here `props` should contain all of the original
     `propsForComponentB` passed to ComponentB initially, 
      plus the extra prop `componentAmethod`
  */
  function onSomething(){
     props.componentAmethod(...arguments)
  }

  .....
  ...
}

To give you an example, with Ember.js you can do cool stuff like the below, out of the box:

  <ComponentA as |doSomething|>
    <ComponentB onSomething={doSomething}/>
  </ComponentA>

doSomething is an internal method of <ComponentA> that is made available to whatever children are rendered inside <ComponentA>

Kawd
  • 4,122
  • 10
  • 37
  • 68

1 Answers1

1

The useImperativeHandle is likely what you are after here. It allows you to pass a ref around and then assign information to it.

In the sample below you can see we click a button in ComponentB which triggers the console.log function in ComponentA.

The docs recommend to use this pattern sparingly. So perhaps have a think about a different structure of your code that might help avoid using refs if not necessary.

export default function App() {
  const inputRef = useRef();

  return (
    <>
      <span>App Title</span>
      <br />
      <ComponentA inputRef={inputRef}>
        <ComponentB inputRef={inputRef} />
      </ComponentA>
    </>
  );
}

export const ComponentA = (props) => {
  const specialFunction = (msg) => {
    console.log(msg);
  };

  // Component A attaches the function
  useImperativeHandle(props.inputRef, () => ({
    specialFunction
  }));

  return (
    <>
      <span>Component A stuff</span>
      <br />
      {props.children}
    </>
  );
};

export const ComponentB = (props) => {
  const handleClick = () => {
    props.inputRef.current.specialFunction("hello");
  };

  return <button onClick={handleClick}>Print Hello</button>;
};

Here it is in a sandbox, check the console as you click: https://codesandbox.io/s/bold-firefly-p8uhtn?file=/src/App.js

Steve
  • 4,372
  • 26
  • 37
  • In your example, `anotherProp` is not a prop of ``. It's coming from whatever component is calling ``. What I want is an *internal* method of `` to be passed to ``. – Kawd May 25 '22 at 23:38
  • I've edited a more detailed sample @SproutCoder , does that help? – Steve May 25 '22 at 23:48
  • It doesn't I'm afraid. Your example changes the premise of the OP actually. In your example `ComponentB` is imported by `ComponentA` which makes things easy. My question was about the `` scenario. – Kawd May 25 '22 at 23:52
  • 1
    Ahhh i think I see. `useImperitiveHandle` might be your answer here. give me a moment to make a sandbox – Steve May 25 '22 at 23:54
  • 1
    Have a look here: https://codesandbox.io/s/bold-firefly-p8uhtn?file=/src/App.js Ill update the answer. – Steve May 26 '22 at 00:08
  • Apparently there was a similar question here: https://stackoverflow.com/questions/32370994/how-to-pass-props-to-this-props-children but regardless of the popularity of the answers, none of them seem to work 100% as the OP intended. It's really mindblowing that React is lacking fundamental features like this one (and others like computed properties) and devs are meant to hack their way around them with lots of unnecessary code. There should be a clear and simple out-of-the-box API for most these things. But I appreciate your time and help. – Kawd May 26 '22 at 00:08
  • Just saw your sandbox. Interesting that there is also this solution. But again this is too verbose for something so obvious. I was expecting a much simpler API provided by React itself. Thank you nonetheless! – Kawd May 26 '22 at 00:11