rectでdomの参照はrefを使う
例えば、次のようにrefを受け取って該当箇所に接続したりする。 react.dev
アニメーション
サイズが変わるときとかにつかえる。
HTMLコンポーネントを見えることろまでスクロール
scroolIntoViewでいける 親はoverflowさせておく?
useLayoutEffect
同期で実行される。
セレクタの練習
htmlを
<html> <head> <link rel="stylesheet" href="sample.css"/> </head> <body> <div class="root"> 根っこ <div class="sub"> 根っこの子供 <div class="subsub"> 根っこの子供の子供 </div> <div class="poge"> 根っこの子供の子供2 </div> </div> <div class="poi"> 根っこの子供2 </div> <div class="poi2"> 根っこの子供3 </div> </div> <div class="tonari"> 根っこの隣 </div> </body> </html>
とする。
cssとして
.root { background-color: red; padding: 30px; } .root > div { padding: 0px 50px; } .root > div > div { background-color: indigo; } div:not([class*="sub"]) { font-size: 50px; } div[class*="sub"] { font-size: 5px; } .sub::first-line { color: yellow; } .poge::after { content: "!"; color: plum; } div:nth-child(3) { color: purple; background-color: greenyellow; }
などが使える。ダサいページができる。
spyonのimport
同一ファイル内にある
function funcA() : B { return funcB()} function funcB() : B { ... }
においてfuncBをモックにしてfuncAを呼んでもモックが呼ばれない。
import * as thisModule from "./funcA" function funcA() : B { return thisModule.funcB()} function funcB() : B { ... }
とすると呼ばれる。つらい。
値を消す
function removeValueSubOrder<T, K extends keyof T, P extends keyof T[K]>( target: T, subOrder: K, keys: P[] ): T { const obj = { ...target } as any for (const key of keys) { obj[subOrder][key] = undefined } return obj as T } function removeValue<T, K extends keyof T>(target: T, keys: K[]): T { const obj = { ...target } as any for (const key of keys) { obj[key] = undefined } return obj as T }
jest mock
関数のモック
import * as Utils from "hogehoge" jest.mock("hogehoge") jest .spyOn(Utils, "hogeFunc") .mockReturnValue(exampleValue)
置き換え
作ってみた。
const replace: <T, S extends T>( list: T[], condition: (ob: T) => ob is S, callback: (ob: S) => T ) => T[] = (list, condition, callback) => list.map(t => (condition(t) ? callback(t) : t))
Gridを独自コンポーネントにする
(props) => react.componentにするだけで使えるようになる。
const useStyles = (theme: Theme) => { return makeStyles({ root: { flexGrow: 1 }, paper: { padding: theme.spacing(2), textAlign: 'center', color: theme.palette.text.secondary } }) } const Conainer = (props:any) => <Grid container {...props}/> const Item = (props:any) => <Grid item {...props}/> const UnderStandingBreakpoints2 = () => { const theme = useTheme() const classes = useStyles(theme)() return ( <div className={classes.root}> <Conainer spacing={4}> <Item xs={12} sm={6} md={3}> <Paper className={classes.paper}> xs = 12 sm = 6 md = 3 </Paper> </Item> <Item xs={12} sm={6} md={3}> <Paper className={classes.paper}> xs = 12 sm = 6 md = 3 </Paper> </Item> <Item xs={12} sm={6} md={3}> <Paper className={classes.paper}> xs = 12 sm = 6 md = 3 </Paper> </Item> <Item xs={12} sm={6} md={3}> <Paper className={classes.paper}> xs = 12 sm = 6 md = 3 </Paper> </Item> </Conainer> </div> ) }; export default UnderStandingBreakpoints2
Gridにスタイルをあてる
makeStylesを使う。
const useStyles = (theme:Theme) => { return makeStyles({ root: { flexGrow: 1 }, paper: { padding: theme.spacing(2), textAlign: 'center', color: theme.palette.text.secondary } }) }
これをuseStyleしてやればよいだけ。
const UnderStandingBreakpoints = () => { const theme = useTheme() const classes = useStyles(theme)() return ( <div className={classes.root}> <Grid container spacing={4}> <Grid item xs={12} sm={6} md={3}> <Paper className={classes.paper}> xs = 12 sm = 6 md = 3 </Paper> </Grid> <Grid item xs={12} sm={6} md={3}> <Paper className={classes.paper}> xs = 12 sm = 6 md = 3 </Paper> </Grid> <Grid item xs={12} sm={6} md={3}> <Paper className={classes.paper}> xs = 12 sm = 6 md = 3 </Paper> </Grid> <Grid item xs={12} sm={6} md={3}> <Paper className={classes.paper}> xs = 12 sm = 6 md = 3 </Paper> </Grid> </Grid> </div> ) }; export default UnderStandingBreakpoints
サイズは
xs>0px sm>=600px md>=960px lg>1280px xl>1920px
で適応される。画面全体は12分割されそのうちどのわりあいになるかを指定している。
UITextViewでAttributeTextが改行されない
let style = NSMutableParagraphStyle()
style.lineBreakMode = .byWordWrapping
してaddAttributeする。
セルの高さが自動設定されない
セルのコンテンツビュー内で高さと上下の設定をきちんといれてないとそうなる。
構造体を文字列としてみる
struct Hoge { let name:String let age:Int } extension String.StringInterpolation { mutationg func appendInterpolation(_ value: User) { appendInterpolation("Hoge's name is \(value.name) and he name is \(value.age)") } }
としておいて、
let hoge = Hoge(name:"poi", age:44) print("Hoge deatil \(hoge)) /// ここでhogeを引数にとっていることがポイント
これはCustomStringConvertibleと同じである。
しかし、こんなこともできる・
引数を好きなだけとれるのだ
extension String.StringIterpolation { mutating func appendInterpolation(_ number: Int, style:NumberFormatter.Style) { formatter.numberStyle = style if let result = formatter.string(from: number as NSNumber) { appendLiteral(result) } }
これで $20とか、1st, 12thとかできる。
let number = Int.random(in:0...100) let lucky = "lucky number this weeks os \(number, style: .spellOut)." print(lucky)
appendLiteralは必要に応じて何度も呼べる。
extension String.StringInterpolation { mutating func appendInterpolation(repeat str: string, _ count:Int) { for _ in 0..< count { appendLiteral(str) } } } print("say, \(repat: "hello!,", 3)
他のSwiftの機能と組み合わせて例えば配列がないときはデフォルト表示するなどできる。
extension String.StringInterpolation { mutating func appendInterpolation(_ value:[String], empty defaultValue:@autoclosure () -> String) { if value.count == 0 appendLiteral(defaultValue()) } else { appendLiteral(values.joined(separator:",")) } } } let particle = ["fermion", "boson"] print("List of particle: \(names, empty: "No one").") @autoclosureを使うことで単純なあたいや、複雑な関数を呼び出しできる。 ExpressibleByStringLiteralやExpressibleByStringInterpolationなどと組み合わせることで 文字列補間で全体の型を作れるようになり、CustomStringConvertibleを通してその型をprintできるようにさえなった。 必要なことは ExpressibleByStringLiteralとExpressibleByStringInterpolationに準拠することで必要ならCustomStringConvertibleにも準拠すること。 自分の型の中にネストしてStringInterpolation構造体を作りStringInterpolationProtocolに準拠させる。その初期化には期待する大まかなデータ量を入れる必要がある。また、appendLiteral() を実装する必要がある。appendInterpolation()もいる。 初期化も2ついる。 様々な共通エレメントからHTMLを構成する型を例につくろう。
struct HTMLComponent: ExpressibleByStringLiteral, ExpressibleByStringInterpolation, CustomStringConvertible { struct StringInterpolation: StringInterpolationProtocol { // start with an empty string var output = ""
// allocate enough space to hold twice the amount of literal text
init(literalCapacity: Int, interpolationCount: Int) {
output.reserveCapacity(literalCapacity * 2)
}
// a hard-coded piece of text – just add it
mutating func appendLiteral(_ literal: String) {
print("Appending \(literal)")
output.append(literal)
}
// a Twitter username – add it as a link
mutating func appendInterpolation(twitter: String) {
print("Appending \(twitter)")
output.append("<a href=\"https://twitter/\(twitter)\">@\(twitter)</a>")
}
// an email address – add it using mailto
mutating func appendInterpolation(email: String) {
print("Appending \(email)")
output.append("<a href=\"mailto:\(email)\">\(email)</a>")
}
}
// the finished text for this whole component
let description: String
// create an instance from a literal string
init(stringLiteral value: String) {
description = value
}
// create an instance from an interpolated string
init(stringInterpolation: StringInterpolation) {
description = stringInterpolation.output
}
}
let text: HTMLComponent = "You should follow me on Twitter (twitter: "twostraws"), or you can email me at (email: "paul@hackingwithswift.com")." print(text) /// You should follow me on Twitter @twostraws, or you can email me at paul@hackingwithswift.com.
これでHTMLが吐き出されるが、他にも使い方がありそう。 参考文献 [https://github.com/twostraws/whats-new-in-swift-5-0:title]