Crie layout flexível e componentes de interface do usuário compostos sem a necessidade de definir adereços personalizados arbitrários.
npm i macro-components
import React from 'react'
import styled from 'styled-components'
import Macro from 'macro-components'
import { space , fontSize , color } from 'styled-system'
// Define some styled-components
const Box = styled . div ` ${ space } ${ fontSize } ${ color } `
Box . displayName = 'Box'
const Image = styled . img `
max-width: 100%;
height: auto;
${ space }
`
Image . displayName = 'Image'
const Heading = styled . h2 ` ${ space } ${ fontSize } ${ color } `
Heading . displayName = 'Heading'
const Text = styled . div ` ${ space } ${ fontSize } ${ color } `
Text . displayName = 'Text'
// create a macro function with the UI components you intend to use
const macro = Macro ( {
Image ,
Heading ,
Text
} )
// Create a macro-component
const MediaObject = macro ( ( {
Image ,
Heading ,
Text
} ) => (
< Flex p = { 2 } align = 'center' >
< Box width = { 128 } >
{ Image }
</ Box >
< Box >
{ Heading }
{ Text }
</ Box >
</ Flex >
) ) import MediaObject from './MediaObject'
// get the macro component's child components
const { Image , Heading , Text } = MediaObject
// Use the macro-component by passing the components as children
const App = props => (
< div >
< MediaObject >
< Image src = 'kitten.png' />
< Heading >
Hello
</ Heading >
< Text >
This component keeps its tree structure but still allows for regular composition.
</ Text >
</ MediaObject >
</ div >
) Nota: Os componentes macro têm como objetivo trabalhar apenas com componentes infantis específicos. Se você deseja definir slots , consulte a seção Alternativas abaixo.
Freqüentemente, é melhor usar a composição do React e props.children para criar a interface do usuário composta por vários elementos, mas às vezes você pode criar componentes compostos maiores com estruturas de árvores encapsuladas para layout ou criar componentes da interface do usuário do tipo Bootstrap, como painéis, cartões ou alertas. Esta biblioteca permite criar componentes compostos com estruturas DOM encapsuladas sem a necessidade de definir APIs arbitrárias de adereços e que funcionam como qualquer outra composição do React.
Isso pode ajudar a garantir que sua área de superfície da API componente permaneça pequena e fácil de manter.
Se você estiver criando componentes de reação composta que não mapeiam para estruturas de dados, conforme descrito no pensamento no React, este módulo se destina a você.
Macro(componentsObject)(elementFunction)
Retorna um componente REACT com uma API composta que mantém a estrutura do layout de árvores.
const Banner = Macro ( {
// pass a components object
Heading ,
Subhead
} ) ( ( {
// the element function receives child elements
// named according to the components object
Heading ,
Subhead
} ) => (
< Box p = { 3 } color = 'white' bg = 'blue' >
{ Heading }
{ Subhead }
</ Box >
) O argumento elementFunction é chamado com um objeto de elementos baseados no componentsObject passado para a função macro. Usar o componente de banner acima se pareceria com o seguinte.
import Banner from './Banner'
const App = ( ) => (
< Banner >
< Banner . Heading > Hello </ Banner . Heading >
< Banner . Subhead > Subhead </ Banner . Subhead >
</ Banner >
)O objeto de componentes é usado para definir quais componentes o componente macro aceitará quando crianças.
A função do elemento é semelhante a um componente React, mas recebe um objeto de elementos como seu primeiro argumento e apoio como o segundo. O objeto Elements é criado a partir de seus filhos e pretende facilitar a composição e as estruturas de elementos da encapsulação.
Dentro do componente macro, a função do elemento é chamada com o objeto de elementos e os adereços: elementFunction(elementsObject, props) .
// example
const elFunc = ( { Heading , Text , } , props ) => (
< header >
{ Heading }
{ Text }
</ header >
)
const Heading = styled . h2 ``
const Text = styled . div ``
const componentsObj = {
Heading ,
Text
}
const SectionHeader = Macro ( componentsObj ) ( elFunc ) Para qualquer elemento que não seja aprovado quando criança para o componente macro, a função do elemento tornará undefined e o reação não renderá esse elemento. Isso é útil para omitir condicionalmente crianças opcionais
const macro = Macro ( { Icon , Text , CloseButton } )
const Message = macro ( {
Icon ,
Text ,
CloseButton
} ) = > (
< Flex p = { 2 } bg = 'lightYellow' >
{ Icon }
{ Text }
< Box mx = 'auto' />
{ CloseButton }
</ Flex >
) import Message from './Message'
const { Text , CloseButton } = Message
// Omitting the Icon child element will render Message without an icon.
const message = (
< Message >
< Text > { props . message } </ Text >
< CloseButton
onClick = { props . dismissMessage }
/>
</ Message >
)O segundo argumento passado para a função do elemento permite passar adereços para o elemento raiz ou qualquer outro elemento dentro do componente.
const macro = Macro ( { Image , Text } )
const Card = macro ( ( {
Image ,
Text
} , props ) => (
< Box p = { 2 } bg = { props . bg } >
{ Image }
{ Text }
</ Box >
) ) // example usage
< Card bg = 'tomato' >
< Card . Image src = 'kittens.png' />
< Card . Text > Meow </ Card . Text >
</ Card >Para aplicar adereços padrão aos elementos passados como crianças, use o componente clone em uma função de elemento.
import Macro , { Clone } from 'macro-components'
import { Heading , Text } from './ui'
const macro = Macro ( { Heading , Text } )
const Header = macro ( ( { Heading , Text } ) => (
< Box p = { 2 } >
< Clone
element = { Heading }
fontSize = { 6 }
mb = { 2 }
/>
< Clone
element = { Text }
fontSize = { 3 }
/>
</ Box >
) )Para usar o mesmo componente duas vezes, dê uma chave exclusiva no componentObject.
import React from 'react'
import Macro from 'macro-components'
import { Heading } from './ui'
const macro = Macro ( {
Heading : Heading ,
Subhead : Heading
} )
const Header = macro ( ( { Heading , Subhead } ) => (
< Box p = { 2 } >
{ Heading }
{ Subhead }
</ Box >
) ) < Header >
< Header . Heading > Hello </ Header . Heading >
< Header . Subhead > Subhead </ Header . Subhead >
</ Header >Para criar componentes de layout que não são acoplados a componentes infantis específicos, o uso de adereços ou crianças ordenadas é provavelmente uma abordagem mais simples.
As soluções abaixo permitem que você passe quaisquer componentes arbitrários como adereços ou filhos.
Veja esta discussão para mais.
// using custom props
const MyLayout = ( {
left ,
right
} ) => (
< Flex >
< Box width = { 128 } >
{ left }
</ Box >
< Box width = { 1 } >
{ right }
</ Box >
</ Flex >
)
< MyLayout
left = { (
< Image src = 'kitten.png' />
) }
right = { (
< Text > Meow </ Text >
) }
/ > // using ordered children
const Header = props => {
const [ first , second ] = React . Children . toArray ( props . children )
return (
< Box p = { 3 } >
{ first }
{ second }
</ Box >
)
}
< Header >
< Heading > First </ Heading >
< Text > Second < / Text>
</ Header > // using a children object
const Header = ( {
children : {
left ,
right
}
} ) => (
< Flex >
< Box >
{ left }
</ Box >
< Box width = { 1 } >
{ right }
</ Box >
</ Flex >
)
< Header >
{ {
left : (
< Image src = 'kitten.png' />
) ,
right : (
< Text > Meow </ Text >
)
} }
</ Header > MIT Licença