0
votes

I am rendering component Dropdown which acts like html dropdown component, but is a collection of divs ordered and unordered lists. I am trying to pass styles to the className elements , which have dropdown.css file rendering the styles, but I am not sure how to target those specific elements all the way from the parent component. How to target

div className="select-box-current"

with style={{ border: "1px solid #D4D4D4" }}

and

div className="select-box-list"

with

style={{
          opacity: 1,
          display: "inherit",
          animationName: "none",
          cursor: "pointer"
        }}

The CodeSandblox is here -> https://codesandbox.io/s/weathered-wood-cf8u8?file=/src/App.js:481-614

2

2 Answers

1
votes

So with React if you pass props that are the same name, it only select the one that was passed last. So with your two style props, it only would pass the last one. However, it probably isn't the best idea to use the name style anyway, since it isn't descriptive and also mirrors the actual HTML style attribute.

Give the two different styles unique names, in the App.js file:

<div className="App">
  <Dropdown
    inputName="viola"
    list={[
      { yard_id: "1", yard_name: "Yard 1" },
      { yard_id: "2", yard_name: "Yard 2" }
    ]}
    // this style is for  className="select-box-current"
    currentStyles={{ border: "1px solid #D4D4D4" }}
    // this style is for className="select-box-list"
    listStyles={{
      opacity: 1,
      display: "inherit",
      animationName: "none",
      cursor: "pointer"
    }}
  />
</div>

Now we need to pass those two props through your component tree, the next file is the Dropdown.js file.

Before I get to passing the props, I want to comment about something that is wrong, that isn't entirely related.

export const Dropdown = ({ list, ...others }) => {
  const copiedProps = {};
  Object.keys(others).forEach((key) => {
    // these are the props that need to get thru:
    if ("style" === key || "className" === key) {
      copiedProps[key] = others[key];
    }
  });

  ...

The copying of props, isn't necessary and the way that it is done is actually detrimental. If you want to specifically target a value in the incoming props, you can access it directly (ex props.myProp or in this case other.style) or destructuring assignment.

Since you are wanting to only pass the style (now listStyles and currentStyles) and the className I chose to assign them to a variable using the destructuring assignment.

export const Dropdown = ({
  list,
  currentStyles,
  listStyles,
  className,
  ...others
}) => { ... }

Now that we have those props, we want to pass it into your DropdownView which contains the actual elements you're wanting to target.

<DropdownView
  dropdownItems={dropdownItems}
  activeItem={activeItem}
  hover={hover}
  setActiveItem={(activeItem) => {
    setActiveItem(activeItem);
  }}
  onMouseOver={(hover) => onMouseOver(hover)}
  toggleList={() => toggleList(!hideList)}
  hideList={hideList}
  className={className}
  currentStyles={currentStyles}
  listStyles={listStyles}
/>

Okay, now we have the styles and classname where we want them. All you have to do is get the props like we did above, and then set them on the elements.

<div
  className="select-box-current"
  tabIndex="0"
  autoFocus={true}
  onClick={() => toggleList()}
  style={currentStyles}
>...</div>

I forked the sandbox to include a working example. But node that I didn't set the use the className prop in the DropdowView since it wasn't clear what element would have that.

https://codesandbox.io/s/hardcore-sun-yyx0g?file=/src/DropdownView.jsx

1
votes

I think instead of using them from the parent div you can directly use those styles to those elements like this. https://codesandbox.io/s/eloquent-lamport-3spzr?file=/src/App.js

But if you want to use those styles from the parent. Then you can pass them using specific name. Like this

<Dropdown
    inputName="viola"
    list={[
        { yard_id: "1", yard_name: "Yard 1" },
        { yard_id: "2", yard_name: "Yard 2" }
    ]}
    // this style is for  className="select-box-current"
    selectBoxCurrentStyle={{ border: "1px solid #D4D4D4" }}
    // this style is for className="select-box-list"
    selectBoxListStyle={{
        opacity: 1,
        display: "inherit",
        animationName: "none",
        cursor: "pointer"
    }}
/>

Here is the link https://codesandbox.io/s/damp-rain-cyhxb?file=/src/App.js:133-643