2

Hi everyone.

I have:

import React,{useState, useEffect} from 'react'

/* Styles */
import css from './MyComponent.module.sass'

const MyComponent= ({children, className, ...props}) => {
    const onOver = (e) => {
        console.log(e.target.offsetLeft);
    }

    //And here i need to add onOver function to each "children" element as onMouseOver event

    return(
        <ul className={`${css.MyComponentWrap} ${className}`}>
            <div className={css.MyComponent}></div>
            {children}
        </ul>
    );
}

export default MyComponent;

How can I do it?

I searched the Internet for an answer, but did not find anything suitable. Is it possible to make all the code in this component so that nothing needs to be added to the component in which it will be used?

P.S. sorry for my bad english))

upd.

const AnotherComponent = () =>{

    //here is a huge map function

    let mapResult;
    return (
        <MyComponent>
            {mapResult}
        </MyComponent>
    );
}

I have a huge and hard maping thats why I cannot use @Kox `s answer.

and i need some thing like loop in "MyComponent" and add event or pass it as props.

Actually I can but i thing it not a best solution

3 Answers3

4

If you want to pas prop to your children, use React.PureComponent and React.Children API

class MyComponent extends React.PureComponent {
  onOver = event => {
    //do what u want with you event
  }

  render() {
    const childrenHavingOnOverFunction = 
      React.Children.map(this.props.children, child => {
         return React.cloneElement(child, { onOver: this.onOver })
      }
    );

    return (
        <ul className={`${css.MyComponentWrap} ${className}`}>
            <div className={css.MyComponent}></div>
            {childrenHavingOnOverFunction}
        </ul>
    )

  }
};
1

Any reason you can't attach the listener to the parent (here: ul), and use target to identify which element has been "mouseovered"?

function App() {
  return (
    <MyComponent>
      <li>Bob</li>
      <li className="tab">John</li>
      <li>Sally</li>
    </MyComponent>
  );
}

function MyComponent({ children }) {
  
  function handleClick(e) {
    const { target: { offsetLeft } } = e;
    console.log(offsetLeft);
  }
  
  return (
    <ul onMouseOver={handleClick}>
      {children}
    </ul>
  );
}

// Render it
ReactDOM.render(
  <App />,
  document.getElementById("react")
);
ul { width: 100px; }
li:hover { background-color: #efefef; }
.tab { margin-left: 1em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Andy
  • 61,948
  • 13
  • 68
  • 95
0

This seems like a nice use case for render props (via children prop).

Let your component return this:

return(
  <ul className={`${css.MyComponentWrap} ${className}`}>
   <div className={css.MyComponent}></div>
   {children(onOver)}
  </ul>
);

Now MyComponent should accept its children as a function to render:

<MyComponent>
{(onOver) => {
  // your children components now have access to onOver function
}}
</MyComponent>
Kox
  • 834
  • 7
  • 12