reactjs - Typescript: React.forwardRef'den dönen fonksiyona ‘types’ özelliği nasıl eklenir
React'in forwardRef fonksiyonunun dönüş tipine ek özellikler eklemeye çalışıyorum. Bu durumda types özelliği söz konusu. Bunu çalıştırmayı başardım, ancak Typescript konusunda nispeten yeni olduğum için bunu yapmanın daha iyi bir yolu olduğundan emin değilim (ya da uygulamamın tamamen doğru olduğundan %100 emin değilim).
import * as React from "react";
import {
forwardRef,
ReactNode,
ForwardRefExoticComponent,
PropsWithoutRef,
RefAttributes
} from "react";
import { render } from "react-dom";
import "./styles.css";
enum Types {
button = "button",
a = "a"
}
interface Props extends React.ComponentPropsWithoutRef<"div"> {
children?: ReactNode;
className?: string;
type?: Types;
}
interface Button<T> extends ForwardRefExoticComponent<T> {
types: typeof Types;
}
const Button = forwardRef<HTMLDivElement, Props>(
({ children, className, type, ...props }, ref) => {
return (
<div {...props} className={className} ref={ref}>
{children}
<div>{type}</div>
</div>
);
}
) as Button<PropsWithoutRef<Props> & RefAttributes<HTMLDivElement>>;
Button.types = Types;
function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Button title="foo" type={Button.types.button}>
Hello
</Button>
</div>
);
}
const rootElement = document.getElementById("root");
render(<App />, rootElement);
forwardRef tarafından döndürülen tipe types özelliğini eklemek için daha temiz bir yol var mı?
Çalışan sandbox burada: https://codesandbox.io/s/cocky-ishizaka-2s8vy
Cevap #1
Böyle bir şekilde forwardRef kullanarak ne yapmak istediğini anlamaya çalışıyorum.
Ama bir React ref aslında bir HTML DOM öğesine refere eder. Yani, ref'i (ebeveynine) iletilmiş olan iç bileşenin etiket türünü almak için tagName'i kullanabilirsiniz.
DÜZENLEME 2 Eğer bir kaynağa bilgi eklemek istiyorsanız, bunu özniteliklerde ekleyin, örneğin:
<div ref={ref} data-type="a">something</div>
Ref'e sahip olduktan sonra, özniteliği ref.getAttribute("data-type") ile alın
Bileşeni, referansını geri iletecek şekilde yapmak:
const Input = React.forwardRef((props, ref) => <input type="text" ref={ref} />);
Türünü alma:
handleSubmit = e => {
e.preventDefault();
this.setState({
value: this.inputRef.current.value,
typeOfRef: this.inputRef.current.tagName
});
};
Bunu görüntüleme:
render() {
return (
<div>
<h1>React Ref - createRef</h1>
<h3>Value: {this.state.value}</h3>
<h3>Type: {this.state.typeOfRef}</h3>
<form onSubmit={this.handleSubmit}>
<Input ref={this.inputRef} />
<button>Submit</button>
</form>
</div>
);
}
}
https://codepen.io/bonjour123/pen/bGGQQKG
createRef'in fonksiyonel bileşenlerde kullanılamayacağı (kullanılabilir, aşağıdaki düzenlemeye bakın) unutulmamalıdır; fonksiyonel bileşenler, hook'larla birlikte, React'te işleri yapmanın yeni önerilen yoludur. Yine de, çocuklara geçirilen bir geri çağrıyla kolayca değiştirilebilir ve ref oluşturulduğunda çağrılabilir.
Bileşenler bildirimi
const Input = ({ returnBackRef }) => <input type="text" ref={returnBackRef} />;
const Button = ({ returnBackRef, text, handler }) => (
<button onClick={handler} ref={returnBackRef}>{text}</button>
);
Uygulama (fonksiyonel bileşen):
const App = () => {
let [refTo1, setRefTo1] = React.useState({});
let [refTo2, setRefTo2] = React.useState({});
let [info, setInfo] = React.useState({
val1:"",
tag1:"",
val2:"",
tag2:""
});
const handleSubmit = () => {
console.error(info);
setInfo({
val1:refTo1.value,
tag1:refTo1.tagName,
val2:refTo2.textContent,
tag2:refTo2.tagName
});
};
return (
<div >
<h1>React Ref - createRef</h1>
<h3>Value1: {info.val1}</h3>
<h3>Type1: {info.tag1}</h3>
<h3>Value2: {info.val2}</h3>
<h3>Type1: {info.tag2}</h3>
<Input returnBackRef={setRefTo1} />
<Button
handler={handleSubmit}
text={"Submit"}
returnBackRef={setRefTo2}
/>
</div>
);
};
https://codepen.io/bonjour123/pen/VwwVqYR
DÜZENLE Hatalıydım, aslında useRef kullanabilirsiniz, bu functional bileşenler için createRef gibi. Ama bunu başka bir şekilde nasıl uygulayacağınızı görmek yine de havalı, değil mi ^^
