Styled-components — динамический CSS?

#reactjs #styled-components

#reactjs #компоненты в стиле

Вопрос:

У меня есть простое приложение React, которое получает CSS из внешнего источника в форме JSON, стили выглядят так:

 {
  "DOMElements": [
    {
      "padding": "1rem",
      "margin": "5rem",
    },
    {
      "boxSizing": "border-box",
      "height": "10px",
    }
  ]
}
 

Поэтому, когда я получаю ответ, подобный приведенному выше, я хочу получить что-то вроде этого:

 import styled from 'styled-components';

const DOMElement1 = styled.div`
   padding: 1rem,
   margin: 5rem,
`;

const DOMElement2 = styled.div`
   boxSizing: border-box,
   height: 10px,
`;

const Page = ({ children }) => (
  <>
    <DOMElement1>{children[1]}</DOMElement1>
    <DOMElement2>{childrem[2]}</DOMElement2>
  </>
);
 

Стоит отметить, что количество DOMElements в unknown может быть 1, может быть 50.

Составная часть проста, я могу просто делать indexed map и увеличивать индекс в каждом цикле. Проблема, с которой я сталкиваюсь, заключается в том, как мне создать динамические компоненты в стиле компонентов на основе ответа JSON? Мне нужно сделать это внутри самого компонента, поскольку я знаю, как DOMElements он выглядит, но styled-components должны находиться вне функции компонента… Чего мне не хватает? Это вообще выполнимо?

Ответ №1:

Вы можете предоставить реквизиты для стилизованных компонентов.

 const DOMElement1 = styled.div`
   padding: ${({padding}) => padding}rem,
   margin: ${({margin}) => margin}rem,
`;

const Page = ({ children }) => (
  <>
    <DOMElement1 padding={valueFromJson} margin={valueFromJson}>{children[1]}</DOMElement1>
    <DOMElement2 padding={valueFromJson} margin={valueFromJson}>{childrem[2]}</DOMElement2>
  </>
);
 

Комментарии:

1. Я знаю об этом, проблема в том, что у меня не будет двух элементов DOM, их количество будет динамическим / неизвестным, это был просто пример. Я бы использовал children.map вместо жесткого кодирования DOMElements , как в приведенном выше коде.

Ответ №2:

Что-то вроде этого:

 const items = [
  {
    background: "blue",
    width: "30px",
    height: "30px",
    padding:'10px'
  },
  {
    height: "40px",
    background: "red",
    width: "30px",
    padding:'10px'
  }
];

const components = items.map((item) =>
  styled("div")({
    ...item
  })
);

export default function App() {
  return (
    <div style={{ background: "lightblue", width: "100vw", height: "100vh" }}>
      {components.map(Comp => <Comp>hi</Comp>)}
    </div>
  );
}
 

Комментарии:

1. items будут отправлены в качестве реквизита App , поэтому я не могу получить к ним доступ за пределами App компонента: [

2. Вы можете сделать это внутри: return items.map((item) => styled("div")({ ...item }) ).map(C => <C />) }

Ответ №3:

Простым и понятным решением было бы динамически использовать реквизит в вашем стилизованном компоненте, и таким образом вам не нужно беспокоиться о каком-либо входящем свойстве css.

Обратитесь к следующему примеру / этому фрагменту —

 const DOMElement = styled.div`
   ${props => props}
`;

const Page = () => {
  const data = {
    "DOMElements": [
      {
        "padding": "1rem",
        "margin": "5rem",
      },
      {
        "boxSizing": "border-box",
        "height": "10px",
      }
    ]
  };

  return (
    <>
     {data?.DOMElements?.map((obj, index) => 
        <DOMElement {...obj} key={index}>abcd</DOMElement>
      )}
    </>
  );
}
 

Привязка вывода —
загрузка привязки вывода