如何从父组件访问嵌套组件?
How can I accessing nested component in react from parent component?
我想从父组件访问嵌套组件。
我是比尔Form.jsx
import BillDetailForm from './BillDetailForm';
render(){
return (
<form onSubmit={handleSubmit}>
<FieldArray
name= 'detail'
component={BillDetailForm}
placeholder= '...detail'
label='Detail'
/>
</form>
);
}
}
BillForm 是父组件。
这是 BillForm 的嵌套组件或子组件:BillDetailForm.jsx
render(){
return(
<form onSubmit={ handleSubmit }>
<div>Detail:</div>
<FieldArray
name= 'detail'
component={RenderDetail}
label='Detail'
/>
</form>
)
}
BillDetailForm 内部是 RenderDetail:
const RenderDetail = ({fields, meta: { error,submitFailed}},props) => (
<dl>
<dt>
<button type="button" className= 'btn btn-primary' onClick={() => fields.push()}>Add
Detail</button>
{submitFailed && error && <span>{error}</span>}
</dt>
{ fields.map((registerDetail, index) =>
//In the following line renderDetail is accesing Detail component.
<Detail detailItem={registerDetail} fields={fields} index={index} key={index}/>
)
}
{error && <dt className="error">{error}</dt>}
</dl>
);
这是详细信息 Class 组件:
class Detail extends Component{
render(){
const{detailItem,index,fields,isSubtotal} = this.props;
return(
<dd key={index}>
<br></br>
<button className= 'btn btn-light mr-2'
type="button"
title="Remove detail"
onClick={() => { fields.remove(index)
if(fields.length == 0 || fields.length === undefined){
}
try{
for(let x in fields){
fields.remove(index)
let d = fields.selectedIndex;
if(fields.remove(index) && d >= 1 && d< fields.length ){
fields.removeAll(index);
}
}
}catch{console.info("deletes non numerical index")}
}}> Delete </button>
<h4>DetailRegister #{index + 1}</h4>
<Field
id={`${detailItem}._id`}
name={`${detailItem}.quantity`}
component= {NumberPickerInteger}
placeholder= '...quantity'
label = "Quantity"
/>
<br></br>
<h3><b>Product</b></h3>
<Field
id={`${detailItem}._id`}
name={`${detailItem}.product.code`}
type="number"
component= {RenderFieldNumeric}
placeholder='...Product's code'
label = "Product's code"
/>
<Field
id={`${detailItem}._id`}
name={`${detailItem}.product.name`}
type="text"
component= {RenderField}
placeholder='...Product's name'
label = "Product's name"
/>
<Field
id={`${detailItem}._id`}
name={`${detailItem}.product.price`}
component= {NumberPickerr}
placeholder= '...Price'
label = "Product's price"
/>
<br></br>
<h3><b>Subtotal</b></h3>
<Field
id={`${detailItem}._id`}
name={`${detailItem}.subtotal`}
component= {SubtotalWidget}
placeholder= '...subtotal'
label = "Subtotal"
>
{isSubtotal}
</Field>
</dd>
);
}
}
我想访问 BillForm 中的 ${props.detailItem}.subtotal
等详细信息。 BillForm 访问 BillDetailForm,BillDetailForm 访问 renderDetail,最后 renderDetail 访问 Detail。
问题是:如何从 BillForm 访问和使用带有动态索引 (props.index) 的数量和小计等道具?我想从 BillForm 访问 Detail 组件,按照以下顺序访问:BillForm -> BillDetailForm -> RenderDetail -> Detail
如果我没看错你的话,你似乎违背了 React 的精神。如果您的父组件想要访问一段数据,那么该数据应该从父组件开始并向下传递。这样,如果数据发生变化,它将调用组件的重新渲染并更新所有必要的组件。
其他一些建议。尽量不要在组件处理程序中包含太多逻辑,它看起来很乱并且每个渲染周期都会 运行。将其抽象为 class 上的方法,并在需要时调用它。
我的示例有望帮助您解决问题,但我建议您阅读 React 文档,因为它非常适合简单示例。
class 的使用最终将被弃用,以支持函数组件和 Hooks API.
class ParentComponent {
state = {
value: 0,
}
methodToDoSomething = (passedVal) => {
this.setState({
value: passVal,
});
}
render() {
const myState = this.state;
return (
<Component {...myState} />
)
}
}
class Component {
state = {}
render() {
const { value , methodToDoSomething } = this.props;
return (
<div onClick={methodToDoSomething}>
{value}
</div>
)
}
}
// Hooks API
const ParentComponent = () => {
const [stateVal, updateState] = React.useState('myString');
return (
<div>
{stateVal}
<Component passedVal={stateVal} passedHandler={updateState} />
</div>
)
}
const Component = ({ stateVal, passedHandler }) => {
function updateMyValue() {
passedHandler('menewvalue');
}
return (
<div onClick={updateMyValue}>
{stateValue}
<div/>
)
}
为了避免将大量传递给所有子组件,我建议您阅读上下文挂钩。
*** 更新 ***
上面的例子是初级的,试图回答提出的问题,解决问题的方法总是有很多。
传递 props 可能会很混乱并且会增加维护开销。大多数较大的应用程序将受益于使用状态库来管理它们的全局状态。上下文 API 是一个很好的工具,可用于包装一组内聚的组件,因此它们可以共享 data/props 而无需 prop-drilling(将 props 传递给许多子组件)。
自定义挂钩是另一种共享数据的好方法。创建一个包含您的数据和任务的任何其他方法的挂钩,并在父组件和子组件中使用这个挂钩来共享所述数据。
我想从父组件访问嵌套组件。
我是比尔Form.jsx
import BillDetailForm from './BillDetailForm';
render(){
return (
<form onSubmit={handleSubmit}>
<FieldArray
name= 'detail'
component={BillDetailForm}
placeholder= '...detail'
label='Detail'
/>
</form>
);
}
}
BillForm 是父组件。
这是 BillForm 的嵌套组件或子组件:BillDetailForm.jsx
render(){
return(
<form onSubmit={ handleSubmit }>
<div>Detail:</div>
<FieldArray
name= 'detail'
component={RenderDetail}
label='Detail'
/>
</form>
)
}
BillDetailForm 内部是 RenderDetail:
const RenderDetail = ({fields, meta: { error,submitFailed}},props) => (
<dl>
<dt>
<button type="button" className= 'btn btn-primary' onClick={() => fields.push()}>Add
Detail</button>
{submitFailed && error && <span>{error}</span>}
</dt>
{ fields.map((registerDetail, index) =>
//In the following line renderDetail is accesing Detail component.
<Detail detailItem={registerDetail} fields={fields} index={index} key={index}/>
)
}
{error && <dt className="error">{error}</dt>}
</dl>
);
这是详细信息 Class 组件:
class Detail extends Component{
render(){
const{detailItem,index,fields,isSubtotal} = this.props;
return(
<dd key={index}>
<br></br>
<button className= 'btn btn-light mr-2'
type="button"
title="Remove detail"
onClick={() => { fields.remove(index)
if(fields.length == 0 || fields.length === undefined){
}
try{
for(let x in fields){
fields.remove(index)
let d = fields.selectedIndex;
if(fields.remove(index) && d >= 1 && d< fields.length ){
fields.removeAll(index);
}
}
}catch{console.info("deletes non numerical index")}
}}> Delete </button>
<h4>DetailRegister #{index + 1}</h4>
<Field
id={`${detailItem}._id`}
name={`${detailItem}.quantity`}
component= {NumberPickerInteger}
placeholder= '...quantity'
label = "Quantity"
/>
<br></br>
<h3><b>Product</b></h3>
<Field
id={`${detailItem}._id`}
name={`${detailItem}.product.code`}
type="number"
component= {RenderFieldNumeric}
placeholder='...Product's code'
label = "Product's code"
/>
<Field
id={`${detailItem}._id`}
name={`${detailItem}.product.name`}
type="text"
component= {RenderField}
placeholder='...Product's name'
label = "Product's name"
/>
<Field
id={`${detailItem}._id`}
name={`${detailItem}.product.price`}
component= {NumberPickerr}
placeholder= '...Price'
label = "Product's price"
/>
<br></br>
<h3><b>Subtotal</b></h3>
<Field
id={`${detailItem}._id`}
name={`${detailItem}.subtotal`}
component= {SubtotalWidget}
placeholder= '...subtotal'
label = "Subtotal"
>
{isSubtotal}
</Field>
</dd>
);
}
}
我想访问 BillForm 中的 ${props.detailItem}.subtotal
等详细信息。 BillForm 访问 BillDetailForm,BillDetailForm 访问 renderDetail,最后 renderDetail 访问 Detail。
问题是:如何从 BillForm 访问和使用带有动态索引 (props.index) 的数量和小计等道具?我想从 BillForm 访问 Detail 组件,按照以下顺序访问:BillForm -> BillDetailForm -> RenderDetail -> Detail
如果我没看错你的话,你似乎违背了 React 的精神。如果您的父组件想要访问一段数据,那么该数据应该从父组件开始并向下传递。这样,如果数据发生变化,它将调用组件的重新渲染并更新所有必要的组件。
其他一些建议。尽量不要在组件处理程序中包含太多逻辑,它看起来很乱并且每个渲染周期都会 运行。将其抽象为 class 上的方法,并在需要时调用它。
我的示例有望帮助您解决问题,但我建议您阅读 React 文档,因为它非常适合简单示例。 class 的使用最终将被弃用,以支持函数组件和 Hooks API.
class ParentComponent {
state = {
value: 0,
}
methodToDoSomething = (passedVal) => {
this.setState({
value: passVal,
});
}
render() {
const myState = this.state;
return (
<Component {...myState} />
)
}
}
class Component {
state = {}
render() {
const { value , methodToDoSomething } = this.props;
return (
<div onClick={methodToDoSomething}>
{value}
</div>
)
}
}
// Hooks API
const ParentComponent = () => {
const [stateVal, updateState] = React.useState('myString');
return (
<div>
{stateVal}
<Component passedVal={stateVal} passedHandler={updateState} />
</div>
)
}
const Component = ({ stateVal, passedHandler }) => {
function updateMyValue() {
passedHandler('menewvalue');
}
return (
<div onClick={updateMyValue}>
{stateValue}
<div/>
)
}
为了避免将大量传递给所有子组件,我建议您阅读上下文挂钩。
*** 更新 *** 上面的例子是初级的,试图回答提出的问题,解决问题的方法总是有很多。
传递 props 可能会很混乱并且会增加维护开销。大多数较大的应用程序将受益于使用状态库来管理它们的全局状态。上下文 API 是一个很好的工具,可用于包装一组内聚的组件,因此它们可以共享 data/props 而无需 prop-drilling(将 props 传递给许多子组件)。
自定义挂钩是另一种共享数据的好方法。创建一个包含您的数据和任务的任何其他方法的挂钩,并在父组件和子组件中使用这个挂钩来共享所述数据。