При использовании withStyles()
hoc в машинописном тексте я получаю следующую ошибку при попытке использовать возвращенный компонент:
Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<App> & Readonly<{ children?: ReactNode; }> & Reado...'.
Type '{}' is not assignable to type 'Readonly<WithStyles<"main">>'.
Property 'classes' is missing in type '{}'.
Похоже, что это изменение определения типа может быть связано с этой проблемой.
Учитывая приведенный ниже код компонента App
, я смогу использовать компонент <App />
без ошибки типа, как это было в 1.0.0-beta.10.
Учитывая приведенный ниже код компонента App
, попытка использовать <App />
приводит к вышеупомянутой ошибке.
import * as React from 'react';
import { withStyles } from 'material-ui/styles';
const styles = {
main: {
marginTop: 48,
padding: 10,
},
foo: {
margin: 0,
},
};
interface Props {
message: string;
};
type ClassNames = { classes: { [className in keyof typeof styles]: string } };
class App extends React.Component<Props & ClassNames> {
render() {
const { classes, message } = this.props;
return (
<div className={classes.main}>
<div className={classes.foo} >
Hello World! {message}
</div>
</div>
);
}
}
export default withStyles(styles)(App);
Код работал нормально в 1.0.0-beta.10, когда я обновился до 1.0.0-beta.12, я получил ошибку типа.
В предоставленном фрагменте кода я использовал уловку keyof typeof styles
чтобы мне не нужно было дважды определять список имен классов (мне категорически не нравится повторяемость). Я также пробовал другие варианты:
type ClassNames = WithStyles<keyof typeof styles>;
и делаем это более распространенным способом (как показано в styles.spec.tsx ):
type ComponentClassNames = 'main' | 'foo';
type ClassNames = WithStyles<ComponentClassNames>;
Я все еще получаю ту же ошибку.
Кажется, что предыдущее определение типа вернет компонент, тип реквизита которого будет StyledComponentProps
который имеет необязательное свойство classes
. Новое определение ...
<P, C extends React.ComponentClass<P & StyledComponentProps<Names>>>(
component: C
): C;
... возвращает тот же тип C
что и компонент, это означает, что передача ClassNames
которая не помечена как необязательная, распространяется на возвращаемый компонент. Я вижу здесь упомянутое использование Partial<>
которое я считаю неприглядным.
| Технология | Версия |
| -------------- | --------- |
| Материал-UI | 1.0.0-beta.12 |
| Реагировать | 15.6.1 |
| браузер | Хром 61.0.3163.100 |
@cfilipov при декорировании класса компонента вы должны использовать StyledComponentProps
вместо WithStyles
, а если в режиме строгой проверки типа вам нужно использовать ненулевой оператор утверждения !
для извлечения поля classes
. Это компромисс, позволяющий использовать withStyles
в качестве декоратора класса. Декораторы классов в TypeScript страдают от ограничения , заключающегося в
withStyles
в качестве декоратора классаclasses
при создании элемента декорированного типа компонента (предыдущий компромисс, который, возможно, был более раздражающим )classes
считалось допускающим значение NULL внутри компонента, вынуждая вас использовать оператор !
при доступе к его полям ( текущий компромисс )Я настоятельно рекомендую, чтобы, если ваш компонент не имеет состояния, вы использовали функциональный компонент без состояния, который потребует меньше аннотаций типов и будет более безопасным по типу:
export default withStyles(styles)<Props>(({ classes, message }) => (
<div className={classes.main}>
<div className={classes.foo}>
Hello World! {message}
</div>
</div>
));
Я вижу здесь упомянутое использование Partial <>, которое я считаю неприглядным.
Если вы прочитаете мое продолжение к этому комментарию, вы увидите, что Partial<>
не требуется.
Если вы прочитаете мое продолжение к этому комментарию, вы увидите, что Partial <> не требуется.
Я видел ваш комментарий по поводу Partial<>
. Использование StyledComponentProps
сути означает одно и то же (в этом определении используется Partial<>
). Моя претензия к этому заключается в том, что теперь к именам классов необходимо обращаться с помощью !
(как вы упомянули). Я думаю, что передача фиктивного classes
prop или требование использования !
- плохой компромисс.
Чтобы прояснить, я предполагаю, что основная проблема, с которой я здесь сталкиваюсь, - это выбор ввести регрессию в hoc в попытке обойти ограничение экспериментальной функции машинописного текста. Я признаю некоторую предвзятость, так как меня не волнуют декораторы, в то время как другие явно любят, но компромисс здесь не имеет для меня смысла.
@cfilipov моим первым рефакторингом типизации withStyles
было выбрать вариант (1), т.е. сделать типизацию полностью правильной для компонентов класса и функции, за счет использования withStyles
в качестве декоратора класса. . Затем я получил обратную связь , что с помощью синтаксиса декоратора был популярным запросом, поэтому я перешел на вариант (3). Я счастлив пересмотреть это решение; Я тоже предпочел бы безопасность типов поддержке декораторов в их текущем полуфункциональном состоянии.
Да, я понимаю желание поддержать такую популярную просьбу. Я тоже хочу использовать декораторы, но каждый раз сталкиваюсь с множеством проблем с ними (кроме mui), поэтому я лично решил не использовать их, пока они не будут готовы.
Похоже, вы разделяете мою озабоченность, и мне нечего добавить, поэтому, надеюсь, другие люди могут предоставить обратную связь в этом направлении, чтобы помочь повлиять на нее.
Я перешел на beta.13 с beta.10, чтобы посмотреть, не изменилось ли что-нибудь, и да, это реальная проблема. Чтобы бросить сюда мои 2 цента, декораторы для меня экспериментальные. Очевидно, что в будущем они могут быть изменены. А до тех пор я полностью поддержу 100% точный способ. Я бы предпочел иметь согласованную безопасность типов, чем взламывать свои типы, чтобы все работало.
@withStyles()
в качестве декоратора (в TypeScript).Вот как бы выглядело "украшение" класса, если бы мы сделали правильную типизацию:
type NonStyleProps = {
text: string
};
const styles = {
root: {
backgroundColor: 'red'
}
};
const DecoratedComponent = withStyles(styles)(
class extends React.Component<NonStyleProps & WithStyles<'root'>> {
render() {
return (
<div className={this.props.classes.root}>
{this.props.text}
</div>
);
}
}
);
@pelotom Из-за этой проблемы мне еще предстоит перейти от beta.10. Раньше я прокомментировал стиль класса с помощью метода подключения Redux. Я думаю, что это относительно просто и надежно. в # 8059 третий комментарий относится к типам.
@pelotom Большое спасибо за то, что withStyles
отказался от поддержки декораторов, чтобы повысить безопасность типов.
мы должны рассмотреть отказ от поддержки @withStyles () в качестве декоратора (в TypeScript).
@pelotom Я лично за это изменение. @sebald Что ты хочешь здесь делать?
Это простое изменение; Я пошел дальше и открыл PR на случай, если вы захотите пойти с этим 🙂
@pelotom, будет ли набор текста работать, если я использую его вот так?
interface IStyles {
// styles interface
}
interface IHeaderInfoStyles {
classes: any;
}
interface IHeaderInfoProps {
// properties resulting from dispatches
}
interface IHeaderInfoInjectedProps {
// props injected from parent if any
}
interface IHeaderInfoDispatchProps {
// dispatches
}
interface IHeaderInfoState {
// your state for the class
}
type HeaderInfoProps = IHeaderInfoProps & IHeaderInfoInjectedProps & IHeaderInfoDispatchProps & IHeaderInfoStyles;
class HeaderInfo extends Component<HeaderInfoProps, IHeaderInfoState> {
export const HeaderInfo_container = withStyles<IHeaderInfoInjectedProps, IStyles>(styles)(
connect<IHeaderInfoProps, IHeaderInfoDispatchProps, (IHeaderInfoInjectedProps & IHeaderInfoStyles)>(mapStateToProps, mapDispatchToProps)(HeaderInfo),
);
@marcusjwhelan withStyles
больше не принимает 2 параметра типа, и вам не нужно предоставлять параметр типа для стилей (его можно вывести из styles
). Вместо этого вы можете написать
withStyles(styles)<NonStyleProps>(...);
Если вы укажете типы для mapStateToProps
и mapDispatchToProps
я могу показать вам, как это будет выглядеть для вашего примера.
tl; dr; Давайте внесем изменения и посмотрим, каков люфт, я думаю 👷🏻
@oliviertassinari @pelotom ¯_ (ツ) _ / ¯ Я не использую декораторы, поэтому лично меня это изменение не волнует, потому что меня это не касается. Но похоже, что многих действительно волнует эта «особенность». Именно поэтому мы добавили его в первую очередь. Это ИМХО то, что здесь в приоритете.
Я очень доволен изменениями withStyles
, но когда вы смотрите на другие более функциональные библиотеки, такие как ramda
или recompose
, типизация не такая строгая, они также не являются супербезопасными. Часто вам нужно передать общий тип, который представляет возвращаемое значение функции. Неприятно, но это будет работать для 99,9% пользователей.
Почему мы не можем вернуть старую типизацию, которая работала для людей, использующих декораторы? Поскольку у него было два универсальных типа, мы могли бы иметь оба набора рядом.
Кроме того, я немного сбит с толку, какие проблемы у людей возникают с декораторами (относительно «неработающих»). Библиотеки, такие как Angular и https://nestjs.com/, в конце концов, активно их используют. В нашем случае люди могут просто добавить WithStyles
к реквизиту, и все будет в порядке.
@sebald
Почему мы не можем вернуть старую типизацию, которая работала для людей, использующих декораторы? Поскольку у него было два универсальных типа, мы могли бы иметь оба набора рядом.
Я не уверен, что вы имеете в виду. Никогда не было набора текста, который позволял бы людям безболезненно использовать декораторы. Первая реализация страдала от # 8267, заключающегося в том, что вы не могли создать элемент декорированного компонента без передачи фиктивного classes
prop, например <StyledComp classes={{} as any} />
. Вторая (текущая) реализация страдает обратной проблемой: classes
потенциально рассматривается как undefined
в классе компонентов. Если вы хотите использовать декораторы TypeScript в их текущей форме, это ваши единственные 2 варианта; выбрать свой яд.
Третий способ - использовать правильный тип, так что classes
определяется внутри класса, но не обязательно для передачи в качестве опоры. Чтобы иметь оба этих условия, вам нужно отказаться от декораторов.
@pelotom Да, извините. Ты прав. На самом деле не мой день ... Итак, давайте объединимся!
@sebald
Кроме того, я немного сбит с толку, какие проблемы у людей возникают с декораторами (относительно «неработающих»). Библиотеки, такие как Angular и https://nestjs.com/, в конце концов, активно их используют.
Я не уверен, как они используются в Angular, но, безусловно, есть случаи, когда декораторы можно использовать безболезненно; в основном, если декоратору не нужно менять тип класса, который он украшает, они работают нормально. Это не та ситуация, которая у нас здесь; withStyles
необходимо изменить тип компонента, который он украшает.
@pelotom Да, именно так. Плохая просто мутация. Фактически, способ, которым TS в настоящее время реализует декораторы, может быть даже хорош для пользователей Angular, поскольку декораторы AFAIK устанавливают контракты с фреймворком, например «зарегистрировать этот класс как компонент» или «добавить метаданные, чтобы я мог использовать это в DI. «... Бог, даже когда я пишу об этом, заставляет меня чувствовать
@pelotom причина, по которой у меня есть типы, - это обеспечение безопасности типов для моих компонентов. В настоящее время типы не имеют типобезопасности, когда дело касается компонентов. InjectedProps в моем примере - это типы, которые требуются компоненту для работы. Типы для подключения от react-redux
необходимости в том , что из реквизита , которые приходят из mapStateToProps и DispatchProps , которые приходят из mapDispatchToProps.
В самом конце должны быть injectedProps, чтобы мой родительский компонент знал, что мне нужно их ввести, иначе мой проект не будет компилироваться. (это то, что я хочу). Переносится ли это изменение обратно на этот тип безопасности?
@marcusjwhelan еще раз, если вы можете предоставить полный (но минимальный) пример, который компилировался в бета-версии 10, я могу показать вам, как выполнить миграцию. AFAIK новая версия должна быть такой же выразительной и более безопасной, чем раньше.
@pelotom Глупый вопрос, есть ли способ получить уведомление о выходе новой версии?
@wcandillon Следуйте за нами в Twitter.
@pelotom Я опубликовал пример выше ... Зачем вам нужно видеть что-то большее, чем это? Вы можете предположить, что это свойства a, b, c, d, e. Единственное, что внедренный реквизит должен быть выдан в качестве требования.
Я понял.
Я вмешиваюсь в это обсуждение немного поздно, но я наблюдал похожую ошибку, о которой упоминалось здесь, и мне еще предстоит определить, как я могу ее исправить. Я использую [email protected]
и [email protected]
.
const LoginForm = withStyles(styles)(
class extends React.Component<WithStyles<'root' | 'button'>, ILoginFormState> {
// ...
}
);
render(
<MuiThemeProvider theme={theme}>
<LoginForm />
</MuiThemeProvider>,
document.getElementById('login-form')
);
В этом конкретном случае я получаю следующее сообщение об ошибке:
Type '{}' is not assignable to type 'IntrinsicAttributes & WithStyles<"root" | "button"> & StyledComponentP...'.
Type '{}' is not assignable to type 'WithStyles<"root" | "button" | "progress" | "textField">'.
Property 'classes' is missing in type '{}'.
not assignable to type 'WithStyles<"root" | "button" | "progress" | "textField">'.
Property 'classes' is missing in type '{}'.
при декорировании класса компонента следует использовать StyledComponentProps вместо WithStyles.
@pelotom - есть ли где-нибудь такой пример? У меня масса проблем с определением стиля класса компонента с отслеживанием состояния в TypeScript.
@iamjem это немного сложно сказать, поскольку вы не предоставили styles
, но похоже, что первая проблема заключается в том, что у вас больше ключей класса, упомянутых в styles
чем вы указываете в WithStyles<...>
. Я думаю, если вы измените его на
const LoginForm = withStyles(styles)(
class extends React.Component<WithStyles<keyof typeof styles>, ILoginFormState> {
// ...
}
);
он должен позаботиться о первой проблеме. Тогда похоже, что есть вторая проблема, которая заключается в том, что результирующий тип LoginForm
равен
React.ComponentType<WithStyles<"root" | "button"> & StyledComponentProps<"root" | "button">>
что явно неверно; похоже, что отсутствие нестилевых реквизитов сбивает с толку систему типов. Вы можете помочь, четко указав, что такое не-style props, передав {}
в качестве аргумента типа:
const LoginForm = withStyles(styles)<{}>( // <-- note the type argument
class extends React.Component<WithStyles<keyof typeof styles>, ILoginFormState> {
// ...
}
);
Извините, это так сложно, я хотел бы знать более простой способ заставить этот материал работать!
Это сработало! Спасибо за быструю помощь @pelotom. Я давно использую React, но совсем недавно перешел на Material-ui и подумал, что попробую Typescript, пока я на нем. Излишне говорить, что я нахожу некоторые крайние случаи, когда трудно сказать, как сделать Typescript счастливым.
Я решил использовать перекомпоновку
пример
import { StyleRules, Theme, withStyles } from "material-ui/styles";
import * as React from "react";
import { compose } from "recompose";
interface IProps {
classes?: any; // <-- add question mark
text: string;
}
const styles = (theme: Theme): StyleRules => ({
root: {
},
});
@compose(
withStyles(styles),
)
export class MyComponent extends React.Component<IProps> {
render() {
const { classes, text } = this.props;
return (
<div className={classes.root}>
{text}
</div>
);
}
}
Я боролся с этой проблемой (и # 8704), но за последние несколько дней не дал однозначного результата. Тогда я последовал совету @pelotom :
вы должны использовать
StyledComponentProps
вместоWithStyles
и искал на GitHub похожие способы решения этой проблемы. И нашел ОДИН рабочий пример 😂. Тем не менее, это хороший вариант, и он решил мою проблему - отдельный контейнер и компонент с TypeScript, являющимся счастливым файлом cookie: упомянутый здесь пример ( Примечание: в моем случае сопоставление компонентов находится в отдельном файле контейнера, но идея заключается в тем же.).
Если кто-то думает, что это плохое решение, я открыт для любых изменений и идей. ПРАВИЛЬНО, я просто рад, что мой код перестал жаловаться.
type Styles = 'foo';
const styles: StyleRulesCallback<Styles> = (theme: Theme) => ({
foo: {
position: 'relative',
}
});
interface Props {
something: string;
}
class Sidebar extends React.Component<Props & WithStyles<Styles>> {
render() {
const { classes, something } = this.props;
return (
<div className={classes.foo}>{something}</div>
);
}
}
export default withStyles(styles)<Props>(Sidebar);
Я не хочу создавать новую проблему, но я пробовал все, что видел в документации, пример и передавал проблемы, даже с перекомпоновкой, но я не могу заставить свой компонент работать, когда я добавляю к нему некоторые свойства.
И ресурсы, которые я нашел, в основном относятся к более старым версиям TS, MUI или даже React.
Вот мой компонент:
import React from 'react';
import AppBar from 'material-ui/AppBar';
import { withStyles, WithStyles, StyleRulesCallback } from 'material-ui/styles';
const styles: StyleRulesCallback<'positionFixed'> = () => ({
positionFixed: {
top: 'auto',
bottom: 0,
},
});
const decorate = withStyles(styles);
interface Props {
someProp: string;
};
export const BottomNav = decorate<Props>(
class extends React.Component<Props & WithStyles<'positionFixed'>, {}> {
render() {
return (
<AppBar />
);
}
}
);
export default BottomNav;
И ошибка:
TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & Props & StyledComponentProps<"positionFixed"> & { children?: ReactNode; }'.
Type '{}' is not assignable to type 'Props'.
Property 'someProp' is missing in type '{}'.
Я новичок в TS, но нахожу страницу документации и пример довольно запутанными и / или неполными.
Если у вас есть идеи, спасибо ;-)
@otroboe , вы
<BottomNav />
Если это так, проблема в том, что вам нужно предоставить опору someProp
(которая требуется в соответствии с вашим определением Props
):
<BottomNav someProp="foo" />
Позор мне ... Ой, позор мне.
Я был так сосредоточен на интеграции TS, что забыл оглянуться и сделать несколько шагов назад.
Большое спасибо @pelotom : smile:
@otroboe Также удалите дублирование строки ...
type Styles = 'positionFixed';
Хотелось бы, чтобы это было проще ...
Да, я тоже это сделал, спасибо: +1:
Я только что столкнулся с той же проблемой, но оказалось, что она возникает только в том случае, если я инициализировал объект стилей в том же файле, что и мой класс или функция. Кроме того, если я импортирую стили из другого файла, я не получаю эту ошибку.
Есть какие-нибудь подсказки, почему это происходит?
@ nishmeht7 вы можете опубликовать автономный сниппет?
@pelotom Я только что работал над его созданием, и он отлично работает в моей песочнице. В настоящее время я работаю над большим приложением и все еще использую версию mui 1.2.2, в то время как моя версия env для песочницы является последней. Поэтому я предполагаю, что после обновления версии я не смогу воспроизвести свою ошибку.
Я последовал примеру базовой формы из https://material-ui.com/demos/selects/, но получил жалобы на то, что в theme
нет root
(с использованием последней версии машинописного текста и материалов- ui), и к элементу form
не применялся класс. Я попытался проследить за обсуждением выше, но это кажется безрезультатным. И действительно, в списке унаследованных классов отсутствовало сгенерированное имя класса для form
. Если я добавил сгенерированное имя класса вручную (найдено в withStyles с помощью console.log(theme)
в инструментах разработки, проверяет элементы, все в порядке, поэтому, очевидно, класс генерируется правильно. Не проходил через withStyles
в form
элемент
Итак, я вернулся к стилям, пока это не будет отсортировано:
<form style = {{display:'flex',flexWrap:'wrap'}} autoComplete="off">
@HenrikBechmann Вы пробовали следовать документации по стилям для машинописного текста? В прошлом мне это очень помогало. https://material-ui.com/guides/typescript/
Спасибо @lookfirst! Я просмотрел (хотя и не сначала :-)) этот документ и использовал
export default withStyles({
root: {
display: 'flex',
flexWrap: 'wrap',
},
})(BaseForm)
(передача объекта, а не функции)
... что позволило избежать ошибок машинописного текста и позволило внедрить сгенерированный класс.
Надеюсь, другие советы помогут с более сложными конструкциями.
Я также подтвердил, что более сложная структура для функции styles
работает (вставляет сгенерированный className
в form
):
import React from 'react'
import { withStyles, createStyles, Theme } from '@material-ui/core/styles'
/*
patterned after first demo https://material-ui.com/demos/selects/ for 3.03
use Typsecript fixes from here: https://material-ui.com/guides/typescript/
*/
const styles = (theme:Theme) => createStyles({
root: {
display: 'flex',
flexWrap: 'wrap',
},
})
class BaseForm extends React.Component<any,any> {
render() {
const { classes } = this.props
return (
<form className = {classes.root} autoComplete="off">
{this.props.children}
</form>
)
}
}
export default withStyles(styles)(BaseForm)
Изменить: @ eps1lon указал, что в этом нет необходимости с использованием WithStyles
!
У меня был некоторый успех, используя ReturnType<T>
чтобы сгенерировать для меня ClassKey
:
import * as React from 'react';
import withStyles, {
StyledComponentProps,
StyleRulesCallback,
} from '@material-ui/core/styles/withStyles';
import { Theme } from '@material-ui/core/styles/createMuiTheme';
const overrideStyles = (theme: Theme) => ({
root: {
display: 'flex',
flexDirection: 'column',
},
});
type Props = StyledComponentProps<keyof ReturnType<typeof overrideStyles>>;
class MyComponent extends React.PureComponent<Props> {
render() {
return <div className={this.props.classes.root}></div>;
}
}
export default withStyles(overrideStyles as StyleRulesCallback, {withTheme: true})(MyComponent);
Использование keyof ReturnType<typeof styleOverrides>
в качестве StyledComponentProps
ClassKey
предоставит вам ключи от объекта, возвращаемого overrideStyles
и избавит вас от необходимости вести список этих ключей вручную. . Единственный сбой, который я заметил, - это ошибка типа, если я не использую overrideStyles as StyleRulesCallback
в вызове withStyles
. Я не уверен на 100%, почему. Я думаю, что withStyles
почему-то не понимает, что такое overrideStyles
.
Чтобы прояснить этот довольно сложный тип, typeof styleOverrides
преобразуется в функцию, возвращающую объект стиля. ReturnType<T>
предоставит вам сам объект стиля. keyof
получит ключи от объекта стиля.
@chrislambe Вам следует руководством по ReturnType
и т. Д. createStyles
и WithStyles
должно быть достаточно в качестве помощников.
@ eps1lon Ой, очень круто! Спасибо!
fwiw Мне все больше нравится пара createStyles / withStyles по мере того, как я их использую. Продвигает аккуратный код, занимается всеми моими проблемами стиля / машинописного текста, и если мне нужен локальный условный CSS, я просто создаю атрибуты локального стиля, которые, конечно, имеют приоритет над классами.
Отлично!!
Следуя руководству по машинописному тексту с @ material-ui / [email protected], я получаю Test does not have required attribute classes
на:
import React from 'react'
import { Theme, WithStyles, withStyles, createStyles } from '@material-ui/core/styles'
const styles = (theme: Theme) => createStyles({
root: {
color: theme.palette.action.active
},
})
interface Props extends WithStyles<typeof styles> {
asd: boolean
}
class TestComponent extends React.Component<Props> {
render() {
const { classes } = this.props
return (
<div className={classes.root}>
</div>
)
}
}
const Test = withStyles(styles)(TestComponent)
const a = () => <Test asd={true}/>
@ aaronlifton2
Пожалуйста, следите за дополнением
@valoricDe Решили проблему?
@TrejGun Я только что проверил. С функциональным компонентом и @ material-ui / [email protected] у меня этой проблемы нет
Я не совсем понимаю.
Следуя документам здесь: https://material-ui.com/guides/typescript/#augmenting -your-props-using-withstyles
кажется, просто приводит к проблеме этой исходной проблемы. Когда вы где-то используете компонент, машинописный текст заставляет вас _пропустить_ свойство классов в качестве опоры вместо того, чтобы понимать, что оно будет _injection_ by withStyles.
Я читаю эти выпуски уже несколько часов и не совсем понимаю. Любая помощь была бы такой приятной на этом этапе.
Относительно этого предложения выше
@cfilipov при декорировании класса компонента вы должны использовать
StyledComponentProps
вместоWithStyles
, а если в режиме строгой проверки типа вам нужно использовать ненулевой оператор утверждения!
для извлечения поляclasses
. Это компромисс, позволяющий использоватьwithStyles
в качестве декоратора класса. Декораторы классов в TypeScript страдают от ограничения , заключающегося в
- не поддерживают использование
withStyles
в качестве декоратора класса- требовать, чтобы вы передавали фиктивную опору
classes
при создании элемента декорированного типа компонента (предыдущий компромисс, который, возможно, был более раздражающим )- требовать, чтобы
classes
считалось допускающим значение NULL внутри компонента, вынуждая вас использовать оператор!
при доступе к его полям ( текущий компромисс )Я настоятельно рекомендую, чтобы, если ваш компонент не имеет состояния, вы использовали функциональный компонент без состояния, который потребует меньше аннотаций типов и будет более безопасным по типу:
export default withStyles(styles)<Props>(({ classes, message }) => ( <div className={classes.main}> <div className={classes.foo}> Hello World! {message} </div> </div> ));
Как я узнал, как использовать StyledComponentProps
? Кажется, я просто передаю строки ключей, определенных в объекте стилей.
Но документы говорят нам сделать что-то, что просто не сработает? что мне не хватает? Мне бы хотелось использовать https://material-ui.com/guides/typescript/#augmenting -your-props-using-withstyles ...
Это возможно?
@valoricDe , как вы сделали функциональный компонент, у которого не было этой проблемы
@TrejGun Я только что проверил. С функциональным компонентом и @ material-ui / [email protected] у меня этой проблемы нет
Я пробую что-то вроде этого:
`` импортировать React, {ChangeEvent, Component, Dispatch} из "реагировать";
импортировать PropTypes из "prop-types";
импортировать из "react-redux";
импортировать {сетку, FormControlLabel, Theme, createStyles, withStyles, Radio, WithStyles} из "@ material-ui / core";
Импортировать сумму из "./Amount";
импортировать {onPastDueFormFieldChange} из "../../store/actions/selectPaymentAmountActions";
const styles = (тема: Тема) =>
createStyles ({
количество: {
alignSelf: "центр",
},
});
интерфейс OwnProps расширяет WithStyles
interface StateProps {
pastDue ?: число;
pastDueOrTotalOrOther: строка;
}
interface DispatchProps {
onPastDueFormFieldChange: OnPastDueFormFieldChange;
}
введите Props = StateProps & DispatchProps & OwnProps;
const PastDueFormField = withStyles (стили) (
({классы, pastDue, pastDueOrTotalOrOther, onPastDueFormFieldChange}: Props) => (
проверено = {pastDueOrTotalOrOther === "pastDue"}
onChange = {onPastDueFormFieldChange}
label = "Просроченный:"
control = {
/>
),
);
const mapStateToProps = (состояние: RootState): StateProps => ({
pastDue: state.customerData.balanceDue.pastDue,
pastDueOrTotalOrOther: state.customerPaymentsForm.pastDueTotalOrOther,
});
экспорт подключения по умолчанию
mapStateToProps,
{onPastDueFormFieldChange},
) (PastDueFormField);
When I use this component I have this error:
```import PastDueFormField
Property 'classes' is missing in type '{}' but required in type 'Readonly<PropsWithChildren<Pick<Pick<Props, "pastDue" | "pastDueOrTotalOrOther" | "onPastDueFormFieldChange"> & StyledComponentProps<"amount">, "classes" | "innerRef"> & OwnProps>>'
@yehudamakarov Попробуйте react-redux
и добавить connect
когда все будет работать должным образом. Невероятно сложно получить хороший обзор, когда вводится пропеллер.
При столкновении с этими проблемами я
missing props
Это продвигает более чистый код. Особенно по порядку действий. В настоящее время вы смешиваете withStyles
и connect
без разделения задач.
Большое спасибо, Себастьян.
Я решил свою проблему, просто не передав общие аргументы для подключения. Я вынул кусок <StateProps ...>
.
Я думаю, что эти общие аргументы мешали моему интерфейсу OwnProps, расширяющему WithStyles <>.
Поскольку я все равно передаю все компоненту, проверки типов, которую я получаю от Props, достаточно. Не уверен, зачем id нужны дженерики connect <>.
Спасибо!
Вот как бы выглядело "украшение" класса, если бы мы сделали правильную типизацию:
type NonStyleProps = { text: string }; const styles = { root: { backgroundColor: 'red' } }; const DecoratedComponent = withStyles(styles)( class extends React.Component<NonStyleProps & WithStyles<'root'>> { render() { return ( <div className={this.props.classes.root}> {this.props.text} </div> ); } } );
А как добавлять темы (useTheme ()) внутрь вроде:
const decorate = withStyles((theme: Theme) => ({
root: {
display: "flex"
},
appBar: {
zIndex: theme.zIndex.drawer + 1,
transition: theme.transitions.create(["width", "margin"], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
})
}
})
Самый полезный комментарий
Я решил использовать перекомпоновку
пример