innerRef
Как получить доступ к внутреннему свойству ref
Иногда бывает необходимо получить доступ к
ref
компонента, лежащего в основе вашего. Это возможно с помощью свойства
innerRef
.
Это свойство принимает функцию, которая будет вызвана с ref'ом внутреннего элемента в качестве аргумента.
Часто вам придется внедрять glamorous
на действующем проекте, который
уже использует глобальный CSS. API glamorous
позволяет сделать
это без лишних усилий.
glamorous
также работает с CSS модулями без дополнительных усилий с вашей
стороны. Это Просто Работает™.
Вот пример с использованием Bootstrap:
// source https://v4-alpha.getbootstrap.com/components/alerts/
import React from 'react';
import { render } from 'react-dom';
import glamorous from 'glamorous';
const Alert = glamorous.div('alert', props => `alert-${props.type}`);
function App() {
return (
<glamorous.Div maxWidth={600} margin="70px auto" fontSize={24}>
<Alert type="success">
<strong>Успех!</strong> Тада! 🎉
</Alert>
<Alert type="info">
<strong>Оповещение!</strong> Кое-какая информация ℹ️
</Alert>
<Alert type="warning">
<strong>Внимание!</strong> Что-то случилось ⚠️
</Alert>
<Alert type="danger">
<strong>Ох блин!</strong> Это совсем не хорошо 🚨
</Alert>
</glamorous.Div>
);
}
render(<App />, document.getElementById('root'));
Попробуйте это в своем браузере здесь!
Если \<Alert success \/> вам больше по душе, чем \<Alert type="success" \/>, то этого просто добиться:
// source https://v4-alpha.getbootstrap.com/components/alerts/
import React from 'react';
import { render } from 'react-dom';
import glamorous from 'glamorous';
const Alert = glamorous.div('alert', props => {
const types = ['success', 'info', 'warning', 'danger'];
return types.reduce((all, t) => {
if (props.hasOwnProperty(t)) {
all = `${all} alert-${t}`;
}
return all;
}, '');
});
function App() {
return (
<glamorous.Div maxWidth={600} margin="70px auto" fontSize={24}>
<Alert success>
<strong>Успех!</strong> Тада! 🎉
</Alert>
<Alert info>
<strong>Оповещение!</strong> Кое-какая информация ℹ️
</Alert>
<Alert warning>
<strong>Внимание!</strong> Что-то случилось ⚠️
</Alert>
<Alert danger>
<strong>Ох блин!</strong> Это совсем не хорошо 🚨
</Alert>
</glamorous.Div>
);
}
render(<App />, document.getElementById('root'));
Попробуйте это в своем браузере здесь!
Запомните
Главная цель CSS в JS - это стилизация компонентов и их повторное
использование. Соответсвтенно, если вам нужно добавить стили всему приложению
в целом (например, html
/body
или добавить reset
стили),
не стоит использовать для этого glamorous
. Вместо этого, используйте обычный
CSS или API glamor для внедрения глобальных стилей.
В дополнение, вместо того, чтобы использовать CSS для стилизации тега a
с помощью глобального CSS, стоит создать компонент Link
, присвоить ему все
необходимые стили и использовать его.
glamorous
полностью поддерживает создание тем с помощью специального
<ThemeProvider>
компонента.
Он предоставляет свойство theme
всем компонентам glamorous, расположенным
ниже в дереве.
import glamorous, {ThemeProvider} from 'glamorous'
// наш главный объект темы
const theme = {
main: {color: 'red'}
}
// наш второстепенный объект темы
const secondaryTheme = {
main: {color: 'blue'}
}
// <Title> компонент с применением темы
const Title = glamorous.h1({
fontSize: '10px'
}, ({theme}) => ({
color: theme.main.color
}))
// используйте <ThemeProvider>, чтобы передать тему ниже в структуре
<ThemeProvider theme={theme}>
<Title>Привет!</Title>
</ThemeProvider>
// можно вкладывать темы друг в друга
// внутренняя тема будет объединена с внешней
<ThemeProvider theme={theme}>
<div>
<Title>Привет!</Title>
<ThemeProvider theme={secondaryTheme}>
{/* это будем синим */}
<Title>Привет отсюда!</Title>
</ThemeProvider>
</div>
</ThemeProvider>
// чтобы сделать override темы, просто передайте свойств theme компоненту glamorous вручную
// компонент проигнорирует любую внешнюю тему и будет использовать ту, которая передана в props
<ThemeProvider theme={theme}>
{/* это будет желтым */}
<Title theme={{main: {color: 'yellow'}}}>Привет!</Title>
</ThemeProvider>
Попробуйте это в своем браузере здесь!
glamorous
также предоставляет компонент высшего порядка withTheme
, так что вы можете получить доступ к своей теме из любого компонента!
import glamorous, {ThemeProvider, withTheme} from 'glamorous'
// наш главный объект темы
const theme = {
main: {color: 'red'}
}
// <Title> компонент с применением темы
const Title = glamorous.h1({
fontSize: '10px'
}, ({theme}) => ({
color: theme.main.color
}))
// обычный компонент, принимающий свойство theme
const SubTitle = ({children, theme: {color}}) => (
<h3 style={{color}}>{children}</h3>
)
// расширенный компонент со свойством theme
const ThemedSubTitle = withTheme(SubTitle)
<ThemeProvider theme={theme}>
<Title>Привет!</Title>
<ThemedSubTitle>от withTheme!</ThemedSubTitle>
</ThemeProvider>
Попробуйте это в своем браузере здесь!
Или если вы предпочитаете декораторы:
import React, {Component} from 'react'
import glamorous, {ThemeProvider, withTheme} from 'glamorous'
// наш главный объект темы
const theme = {
main: {color: 'red'}
}
// <Title> компонент с применением темы
const Title = glamorous.h1({
fontSize: '10px'
}, ({theme}) => ({
color: theme.main.color
}))
// расширенный компонент со свойством theme
@withTheme
class SubTitle extends Component {
render() {
const {children, theme: {main: {color}}} = this.props
return <h3 style={{color}}>{children}</h3>
}
}
<ThemeProvider theme={theme}>
<Title>Привет!</Title>
<SubTitle>от withTheme!</SubTitle>
</ThemeProvider>
withTheme
ожидает, чтоThemeProvider
будет находиться выше в дереве рендера, и вdevelopment
покажет предупреждение, если он не будет найден.
context - это нестабильный API и его не рекомендуется использовать напрямую. Тем не менее, если вам по какой-то причине нужно его использовать, вот пример:
const dynamicStyles = (props, context) => ({
color: context.isLoggedIn ? 'green' : 'red'
})
const MyDiv = glamorous.div(dynamicStyles)
MyDiv.contextTypes = {
isLoggedIn: PropTypes.string,
}
class Parent extends React.Component {
getChildContext() {
return {
isLoggedIn: true,
}
}
render() {
return <MyDiv />
}
}
Parent.childContextTypes = {
isLoggedIn: PropTypes.string,
}
<Parent />
// рендерит <div />
// с {color: 'green'}
Thanks for your interest in helping to update the website translations! The link below will take you to GitHub showing all the changes that happened between the last time /pages/advanced/content/ru/size.md was updated to when the /pages/advanced/content/size.md was most recently updated. Unfortunately this includes all file changes, not just changes in /pages/advanced/content/ru/size.md. So you'll have to click the "Files changed" tab, then search for /pages/advanced/content/ru/size.md in the changes. Then you can open the editor link to update the translation. Thanks again!!
Если в вашем проекте размер является важным ограничением, вам стоит рассмотреть возможность использования "tiny" версии glamorous
.
Это миниатюрная версия glamorous
с рядом ограничений:
glamorous.article({/* styles */ })
)
Так что вам придется создавать свои.
(glamorous('article')({/* styles */ })
)glamorous.Span
)glam
(смотрите пример ниже).ThemeProvider
или withTheme
, придется импортировать их
вручную.
Они не являются частью экспорта glamorous/ tiny
, в отличие от glamorous
.Вот пример того, что вы сможете с этим сделать.
import React from 'react'
import glamorous from 'glamorous/dist/glamorous.es.tiny'
const Comp = glamorous('div')({
color: 'red'
}, (props) => ({
fontSize: props.glam.big ? 20 : 12
}))
function Root() {
return (
<Comp
glam={{ big: true }}
thisWillBeForwardedAndReactWillWarn
>
ciao
</Comp>
)
}
export default Root
Улучшенный экспириенс
Рекомендуется использовать либо
babel-plugin-module-resolver
,
либо resolve.alias
конфигурацию с webpack, чтобы не приходилось импортировать с использованием
полного пути.
У вас есть следующие варианты импорта:
glamorous/dist/glamorous.es.tiny.js
- используйте вместе с Webpack@>=2 или Rollupglamorous/dist/glamorous.cjs.tiny.js
- используйте, если вы не преобразовываете ESModulesglamorous/dist/glamorous.umd.tiny.js
- ипользуйте, если хотите добавить через script тег (Также есть .min.js
версия).Важно
Так как и glamor
и react
поддерживают рендеринг на сервере (SSR), то и glamorous его поддерживает!
Я использую его на своем личном сайте, который генерируется во время билда на сервере. Узнайте больше о рендеринге
react
на сервере и
glamor
.
Для рендера на сервере используйте renderStatic
из glamor
, который принимает callback (функцию обратного вызова). При рендере вашего компонента в callback'е, все вызовы css()
будут собраны, после чего будет возвращен сгенерированный html и css. Также будет возвращен массив id для регидрации стилей, необходимой для быстрого запуска.
Для регидрации вызовите rehydrate
с массивом id, возвращенным из renderStatic
, в качестве аргумента.
Пример -
import {renderStatic} from 'glamor/server'
import {rehydrate} from 'glamor'
import {render} from 'react-dom'
import ReactDOMServer from 'react-dom/server'
let {html, css, ids} = renderStatic(() => ReactDOMServer.renderToString(<App />))
return `
<html>
<head>
<style>${css}</style>
</head>
<body>
<div id="app">${html}</div>
<script src="./bundle.js"></script>
<script>
rehydrate(${JSON.stringify(ids)});
render(<App />, document.getElementById('app'));
</script>
</body>
</html>
`
Посмотрите на этот пример использования glamorous с Next.js
Из-за сложной природы es6 импортов, glamorous может добавлять дубликаты стилей на страницу.
Например:
import App from './App';
rehydrate(${JSON.stringify(ids)}) // id, полученные из renderStatic
Так как import транспилируется раньше остальных выражений, то rehydrate
будет вызван после него, не зависимо в каком порядке вы указываете выражения. Это приводит к созданию дублированных стилей, потому что первым импортируется App
и все стили добавляются прежде, чем будет выполнен rehydrate
.
Чтобы избежать этой проблемы, используйте require()
для выполнения выражений в определенном порядке.
rehydrate(${JSON.stringify(ids)});
const App = require('./App');
Если же вы используете какое-то другое решение, rehydrate
должен всегда вызываться раньше любого другого кода, связанного со стилями.