Продолжаем .... дальше .

Восклицательный знак в начале - это отрицание Не. - Здесь понятно.

То есть если this.state?.done === true, то Не будет false. - Если подразумевается, что ты говорил про восклицательный знак в предыдущем предложении, тогда получается !this.state?.done так как оно изначально было false значит он станет true.

Иначе (то есть false, null, undefined, 0, '' и т.п.) будет приведено к логическому true. (?. здесь примеряется для предотвращения ошибки на случай если объект this.state отсутствует. )

Здесь тоже понятно, что опциональная цепочка ?. проверяет есть ли объект this.state, если его нет он все равно продолжит выполнение. И так как после .? идет done он возьмет текущее состояние стейта объявленое по умолчанию false. (Это предположение здесь уже не понимаю, что реально на самом деле происходит.) И здесь еще кстати появился вопрос, даже если опциональная цепочка ?. проверяет наличие this.state там же стоит восклицательный знак отрицания, тогда получается он опять должен вернуть true.

В итоге получается, что если кликаем, когда state находится в состояние false он отправляет true, если state находится в состоянии false он отправляет true. Только я не понимаю, как вообще обработчик понимает в каком сейчас состоянии находится state, я думал так, что обработчик просто устонавливает и отправляет новое сотояние state, через setState, а получается он его еще и каким-то образом сравнивает его с текущим state.

Или я вообще опять все неправильно понимаю?
Вот такой вот еще приемлемый вариант получился: https://github.com/prisma-cms/nextjs-nexus/commit/1d1cadaf5e2345a6e51a22e24cbc1444f388a698

Сейчас он хотя бы видит когда какие типы есть.

Не получается просто так сделать, и из коробки он тоже не дает таких инструментов.
Тем не менее интересный вариант промежуточный получился:
import { shield } from 'graphql-shield' import { IRuleFieldMap, ShieldRule } from 'graphql-shield/dist/types' import { NexusGenObjects } from 'server/nexus/generated/nexus' type RuleTree = Record<keyof NexusGenObjects, ShieldRule | IRuleFieldMap> const ruleTree: RuleTree = { Query: { // users: rules.users, }, Mutation: {}, } export const permissions = shield(ruleTree)
В таком виде он требует описать правила для всех корневых объектов схемы. Это может пригодиться в режиме "Паранойя". Только надо доработать до дженерика, чтобы можно было и дочерние типы хотя бы для Query и Mutation затребовать.

Рука-лицо... Учи матчасть внимательней. Я зачем уроки сюда с FreeCodeCamp импортировал?
const newValue = !this.state?.done;
Устанавливаем новое значение. Восклицательный знак в начале - это отрицание Не. То есть если this.state?.done === true, то Не будет false. Иначе (то есть false, null, undefined, 0, '' и т.п.) будет приведено к логическому true.

?. здесь примеряется для предотвращения ошибки на случай если объект this.state отсутствует.
this.setState({ done: newValue, })
Устанавливаем значение в стейт.

А наш вариант
this.setState({ done: !this.state?.done, })
это просто сокращенная форма без использования дополнительной переменной newValue.


2. ?? this.state.done здесь вероятнее всего не имеет никакого смысла, то есть можно безболезненно удалить.

Да без него тоже работает.

done: !this.state?.done

Смысл работы этой конструкции вообще не понимаю, как и почему она работает(

И вообще теперь не понимаю почему и эта конструкция работает done: !this.state.done вроде нет никаких условий и все работает прям магия:)

>> В моем же варианте получается возьми или это или другое , другое или это.
Твой вариант - это усложненный мой
handleCardClick = () => { this.setState({ done: !this.state?.done, }) }
К тому же, как я и сказал, если не будет объекта this.state, то будет ошибка. А это совсем не исключено, не всегда классовые компоненты объявляют с инициализацией стейта.

>> Мне кажется самая понятная конструкция получилась.

Это самая неправильная конструкция :)
Точнее, она будет работать, но:
1. Если не будет объекта this.state, то будет ошибка (вспоминаем про ?.).
2. ?? this.state.done здесь вероятнее всего не имеет никакого смысла, то есть можно безболезненно удалить.
Нет, в первом варианте не в скобках дело, а в раскладке (на цифре 7 висят и & и ?). То есть должно быть не done: !(this.state ?? this.state.done), done: !(this.state && this.state.done)
В первом варианте убрал скобки, со скобками не работает:
handleCardClick = () => { this.setState({ done: !(this.state ?? this.state.done), }) }
Получилось так:
handleCardClick = () => { this.setState({ done: !this.state.done ?? this.state.done, }) }
Мне кажется самая понятная конструкция получилась.

Через опциональную цепочку пока не догоняю почему он работает. А в третьем варианте слишком сложная конструкция получается логическое И плюс тернарник. В моем же варианте получается возьми или это или другое , другое или это. Правильно вообще написал и понимаю эту конструкцию?)