如何从父组件调用同一个子组件函数的多个实例
How to call multiple instances of the same child component's function from parent
我知道使用 ref 可以从父组件调用子组件中的函数。但我的问题是我有子组件的多个实例,我需要在所有子组件中调用相同的函数。
// Get a hook function
const {useState, useRef, useImperativeHandle, useEffect} = React;
const Parent = ({title}) => {
const childRef1 = useRef();
const childRef2 = useRef();
const childRef3 = useRef();
const childRef4 = useRef();
const childRef5 = useRef();
const handleClick = () => {
childRef1.current.increment()
childRef2.current.increment()
childRef3.current.increment()
childRef4.current.increment()
childRef5.current.increment()
}
return (
<div>
<p>{title}</p>
<Child num={1} childRef={childRef1} />
<Child num={2} childRef={childRef2} />
<Child num={3} childRef={childRef3} />
<Child num={4} childRef={childRef4} />
<Child num={5} childRef={childRef5} />
<button onClick={() => handleClick()}>
Click me
</button>
</div>
);
};
const Child = ({num, childRef}) => {
const [count, setCount] = useState(0)
useImperativeHandle(childRef, () => ({
increment() {
// if(textEditable)
setCount(count+1)
},
}));
useEffect(() => {
setCount(num)
}, [num])
return (
<div>
{
count
}
</div>
)
}
// Render it
ReactDOM.render(
<Parent title="Example using Hooks:" />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
我的问题是,如果我在 map 函数中渲染子组件,我应该怎么做?
跟踪父级中的状态并将其作为道具传递给子级:
const Parent = ({title}) => {
const [count, setCount] = useState(0);
return (
<div>
<p>{title}</p>
<Child count={count} />
<Child count={count} />
<Child count={count} />
</div>
)
}
如果你需要它们是独立的,使用状态数组:
const Parent = ({title}) => {
const [count, setCount] = useState([0,1,42,96]);
const onIncrement = index => {
// probably a better way to do this. just here for illustrative purposes
const newCount = [...count];
newCount.splice(index, 1, count[index] + 1);
setCount(newCount);
}
const incrementAll = () => setCount(count.map(x => x + 1));
return (
<div>
<p>{title}</p>
{ count.map((entry, index) => (
<Child
num={entry}
key={index}
onIncrement={() => onIncrement(index))} {/* if you want the child to be able to do it */}
/>
)) }
<button onClick={incrementAll}>Click Me</button>
</div>
)
}
I know that using ref's I can call a function...
完美!在那种情况下,我们将使用相同的过程,但只是进一步扩展它。
设置组件或状态来保存子组件...
this.state.children = [];
然后map()
他们就这样...
var children = [1,2,3,4,5,6];
children.map((child) => {
return (
<Child
num={child}
ref={(instance) => {this.state.children[child] = instance}}
/>
);
});
然后调用带有 forEach()
的函数...
Object.keys(this.state.children).forEach((child) => {
var childinstance = this.state.children[child];
childinstance.specialFunction();
});
我是用下面的钩子做的。
// Get a hook function
const {useState, useRef, useImperativeHandle, useEffect} = React;
const Parent = ({title}) => {
const [count, setCount] = useState(0);
const [children, setChildren] = useState(5);
const [childRefs, setChildRefs] = useState([])
const handleClick = () => childRefs.forEach(c => c.current.increment())
useEffect(() => {
setChildRefs([...Array(children).keys()].map(e => React.createRef()))
}, [title])
return (
<div>
<p>{title}</p>
{
[...Array(children).keys()].map(e => <Child
num={e}
childRef={ childRefs[e] }
/>)
}
<button onClick={() => handleClick()}>
Click me
</button>
</div>
);
};
const Child = ({num, childRef}) => {
const [count, setCount] = useState(0)
useImperativeHandle(childRef, () => ({
increment() {
// if(textEditable)
setCount(count+1)
},
}));
useEffect(() => {
setCount(num)
}, [num])
return (
<div>
{
count
}
</div>
)
}
// Render it
ReactDOM.render(
<Parent title="Example using Hooks:" />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
我知道使用 ref 可以从父组件调用子组件中的函数。但我的问题是我有子组件的多个实例,我需要在所有子组件中调用相同的函数。
// Get a hook function
const {useState, useRef, useImperativeHandle, useEffect} = React;
const Parent = ({title}) => {
const childRef1 = useRef();
const childRef2 = useRef();
const childRef3 = useRef();
const childRef4 = useRef();
const childRef5 = useRef();
const handleClick = () => {
childRef1.current.increment()
childRef2.current.increment()
childRef3.current.increment()
childRef4.current.increment()
childRef5.current.increment()
}
return (
<div>
<p>{title}</p>
<Child num={1} childRef={childRef1} />
<Child num={2} childRef={childRef2} />
<Child num={3} childRef={childRef3} />
<Child num={4} childRef={childRef4} />
<Child num={5} childRef={childRef5} />
<button onClick={() => handleClick()}>
Click me
</button>
</div>
);
};
const Child = ({num, childRef}) => {
const [count, setCount] = useState(0)
useImperativeHandle(childRef, () => ({
increment() {
// if(textEditable)
setCount(count+1)
},
}));
useEffect(() => {
setCount(num)
}, [num])
return (
<div>
{
count
}
</div>
)
}
// Render it
ReactDOM.render(
<Parent title="Example using Hooks:" />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
我的问题是,如果我在 map 函数中渲染子组件,我应该怎么做?
跟踪父级中的状态并将其作为道具传递给子级:
const Parent = ({title}) => {
const [count, setCount] = useState(0);
return (
<div>
<p>{title}</p>
<Child count={count} />
<Child count={count} />
<Child count={count} />
</div>
)
}
如果你需要它们是独立的,使用状态数组:
const Parent = ({title}) => {
const [count, setCount] = useState([0,1,42,96]);
const onIncrement = index => {
// probably a better way to do this. just here for illustrative purposes
const newCount = [...count];
newCount.splice(index, 1, count[index] + 1);
setCount(newCount);
}
const incrementAll = () => setCount(count.map(x => x + 1));
return (
<div>
<p>{title}</p>
{ count.map((entry, index) => (
<Child
num={entry}
key={index}
onIncrement={() => onIncrement(index))} {/* if you want the child to be able to do it */}
/>
)) }
<button onClick={incrementAll}>Click Me</button>
</div>
)
}
I know that using ref's I can call a function...
完美!在那种情况下,我们将使用相同的过程,但只是进一步扩展它。
设置组件或状态来保存子组件...
this.state.children = [];
然后map()
他们就这样...
var children = [1,2,3,4,5,6];
children.map((child) => {
return (
<Child
num={child}
ref={(instance) => {this.state.children[child] = instance}}
/>
);
});
然后调用带有 forEach()
的函数...
Object.keys(this.state.children).forEach((child) => {
var childinstance = this.state.children[child];
childinstance.specialFunction();
});
我是用下面的钩子做的。
// Get a hook function
const {useState, useRef, useImperativeHandle, useEffect} = React;
const Parent = ({title}) => {
const [count, setCount] = useState(0);
const [children, setChildren] = useState(5);
const [childRefs, setChildRefs] = useState([])
const handleClick = () => childRefs.forEach(c => c.current.increment())
useEffect(() => {
setChildRefs([...Array(children).keys()].map(e => React.createRef()))
}, [title])
return (
<div>
<p>{title}</p>
{
[...Array(children).keys()].map(e => <Child
num={e}
childRef={ childRefs[e] }
/>)
}
<button onClick={() => handleClick()}>
Click me
</button>
</div>
);
};
const Child = ({num, childRef}) => {
const [count, setCount] = useState(0)
useImperativeHandle(childRef, () => ({
increment() {
// if(textEditable)
setCount(count+1)
},
}));
useEffect(() => {
setCount(num)
}, [num])
return (
<div>
{
count
}
</div>
)
}
// Render it
ReactDOM.render(
<Parent title="Example using Hooks:" />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>