이것을 생각으로 앞장서십시오. 재귀 구성 요소가 필요할 수 있다고 생각하지만 네이티브 js 및 React에 대한 현재 능력을 넘어 서기 때문에 현재 React에 대해 스위스 치즈를 이해하고있는 것 같습니다.
문제 :
다음과 같은 구조의 객체를 metafields
포함 하는 배열이 있습니다 metafield
.
{
metafields: [
{ 0:
{ namespace: "namespaceVal",
key: "keyVal",
val: [
0: "val1",
1: "val2",
2: "val3"
]
}
},
...
]
}
내 코드는 metafields
카드에 매핑 되고 각 카드 <MetafieldInput metafields={metafields['value']} />
내에는 구성 요소가 있으며 해당 구성 요소 내에서 값 배열은 입력 필드에 매핑됩니다. 전반적으로 다음과 같이 보입니다.
// App
render() {
const metafields = this.state.metafields;
return (
{metafields.map(metafield) => (
<MetafieldInputs metafields={metafield['value']} />
)}
)
}
//MetafieldInputs
this.state = { metafields: this.props.metafields}
render() {
const metafields = this.state;
return (
{metafields.map((meta, i) => (
<TextField
value={meta}
changeKey={meta}
onChange={(val) => {
this.setState(prevState => {
return { metafields: prevState.metafields.map((field, j) => {
if(j === i) { field = val; }
return field;
})};
});
}}
/>
))}
)
}
이 시점까지 모든 것이 올바르게 표시 되고 입력을 변경할 수 있습니다! 그러나 변경은 한 번에 하나씩 발생합니다. 키를 누른 다음 다른 문자를 추가하려면 입력을 다시 클릭해야합니다. 모든 것이 다시 렌더링되는 것처럼 보이므로 다른 변경을 위해 입력을 다시 클릭해야합니다.
이런 식으로 구성 요소를 사용할 수 있습니까? 구성 요소를 중첩하는 방식으로 작업하는 것처럼 느껴지지만 읽은 모든 내용은 구성 요소를 중첩하지 말라고 말합니다. 이 문제를 지나치게 복잡하게 만들고 있습니까? 내가 가진 유일한 해결책은 React 부분을 뜯어 내고 순수한 자바 스크립트로 가져가는 것입니다.
안내를 많이 주시면 감사하겠습니다!
내 제안은 onChange 핸들러를 아웃소싱하는 것이며 코드를 조금 더 쉽게 이해할 수 있다는 것입니다.
주로 React setState()
는 호출 직후 상태를 업데이트하지 않고 일괄 작업을 수행합니다. 따라서 여러 setState
호출이 하나의 참조 지점에 액세스 할 수 있습니다 . 상태를 직접 변경하면 배치 작업을 수행하는 동안 다른 상태가 업데이트 된 상태를 사용할 수 있으므로 혼돈을 일으킬 수 있습니다.
또한 앱 수준에서 onChange 핸들러를 소싱하는 경우 MetafieldInputs를 클래스 기반 구성 요소가 아닌 기능 구성 요소로 변경할 수 있습니다. 기능 기반 구성 요소는 클래스 기반 구성 요소보다 비용이 적게 들고 성능을 높일 수 있습니다.
아래는 테스트 된 업데이트 된 코드입니다. Material UI의 TextField를 사용한다고 가정하지만 onChangeHandler는 자체 구성 요소에서도 작동해야합니다.
// Full App.js
import React, { Component } from 'react';
import MetafieldInputs from './MetafieldInputs';
class App extends Component {
state = {
metafields: [
{
metafield:
{
namespace: "namespaceVal",
key: "keyVal",
val: [
{ '0': "val1" },
{ '1': "val2" },
{ '2': "val3" }
]
}
},
]
}
// will never be triggered as from React point of view, the state never changes
componentDidUpdate() {
console.log('componentDidUpdate')
}
render() {
const metafields = this.state.metafields;
const metafieldsKeys = Object.keys(metafields);
const renderInputs = metafieldsKeys.map(key => {
const metafield = metafields[key];
return <MetafieldInputs metafields={metafield.metafield.val} key={metafield.metafield.key} />;
})
return (
<div>
{renderInputs}
</div>
)
}
}
export default App;
// full MetafieldInputs
import React, { Component } from 'react'
import TextField from '@material-ui/core/TextField';
class MetafieldInputs extends Component {
state = {
metafields: this.props.metafields
}
onChangeHandler = (e, index) => {
const value = e.target.value;
this.setState(prevState => {
const updateMetafields = [...prevState.metafields];
const updatedFields = { ...updateMetafields[index] }
updatedFields[index] = value
updateMetafields[index] = updatedFields;
return { metafields: updateMetafields }
})
}
render() {
const { metafields } = this.state;
// will always remain the same
console.log('this.props', this.props)
return (
<div>
{metafields.map((meta, i) => {
return (
<TextField
value={meta[i]}
changekey={meta}
onChange={(e) => this.onChangeHandler(e, i)}
// generally it is not a good idea to use index as a key.
key={i}
/>
)
}
)}
</div>
)
}
}
export default MetafieldInputs
다시 말하지만, onChangeHandler
to App
클래스를 아웃소싱하면 MetafieldInputs
순수한 기능적 구성 요소가 될 수 있으며 모든 상태 관리는 App
클래스 에서 수행 될 수 있습니다 .
반면에 순수하고 깨끗한 App
클래스 를 유지하려면 응용 프로그램에 다른 논리가 필요할 수있는 경우에 대비하여 MetafieldInputs 클래스에 메타 필드를 저장할 수도 있습니다.
예를 들어, 애플리케이션은 예제보다 더 많은 구성 요소를 렌더링하며 MetafieldInputs는 어떤 일이 발생할 때까지 렌더링되지 않아야합니다. 서버 측에서 데이터를 가져 오는 경우 앱 구성 요소의 모든 데이터를 가져 오는 것보다 필요할 때 데이터를 가져 오는 것이 좋습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다