英文:
Access a component state in another component
问题
我有一个名为collection的状态的子组件(CollectionsBar.jsx)。当点击一个div时,它会更新该状态。
我想在父组件(Products.jsx)中访问该状态。所以当状态被点击时,它会改变span标签。
子组件:
import React, { useEffect, useState } from "react";
import useFetch from "../../hooks/useFetch";
import "./CollectionsBar.scss";
const CollectionsBar = () => {
// 设置 useFetch 的数据
const { data, loading, error } = useFetch(
"/collection-list?populate[0]=collecao&populate=FundoTitulo&populate[1]=collecao.Imagem&populate=collecao.products&populate=collecao.products.img&populate=collecao.products.img2"
);
const minifyData = data?.attributes.collecao.data;
const [collection, setCollection] = useState();
// CollectionsBar 组件
return (
<div className="sl-c-collections-bar">
<div className="sl-l-bar__flex">
{minifyData?.map((item, index) => {
return (
<div
onClick={() => {
setCollection(index);
}}
key={index}
className="sl-c-flex__box"
>
<img
src={
import.meta.env.VITE_REACT_APP_UPLOADS_URL +
item.attributes.Imagem.data.attributes.url
}
alt="Imagem Produto"
/>
</div>
);
})}
</div>
</div>
);
};
export default CollectionsBar;
父组件:
import React, { useEffect } from "react";
import useFetch from "../../hooks/useFetch";
import CollectionsBar from "../../components/CollectionsBar/CollectionsBar";
import "./Products.scss";
const Products = () => {
return (
<div className="sl-c-products">
<div className="sl-l-products__flex">
<span></span>
</div>
<CollectionsBar />
</div>
);
};
export default Products;
我只想知道最佳的实现方式...
英文:
I have a children component (CollectionsBar.jsx) with a state named collection. When a div gets clicked, it updates the state.
I want to access the state in the parent's component (Products.jsx). So when the state gets clicked, it changes the span tag.
Children Component:
import React, { useEffect, useState } from "react";
import useFetch from "../../hooks/useFetch";
import "./CollectionsBar.scss";
const CollectionsBar = () => {
//SETTING DATA FOR useFetch
const { data, loading, error } = useFetch(
"/collection-list?populate[0]=collecao&populate=FundoTitulo&populate[1]=collecao.Imagem&populate=collecao.products&populate=collecao.products.img&populate=collecao.products.img2"
);
const minifyData = data?.attributes.collecao.data;
const [collection, setCollection] = useState();
//COLLECTIONS BAR COMPONENT
return (
<div className="sl-c-collections-bar">
<div className="sl-l-bar__flex">
{minifyData?.map((item, index) => {
return (
<div
onClick={() => {
setCollection(index);
}}
key={index}
className="sl-c-flex__box"
>
<img
src={
import.meta.env.VITE_REACT_APP_UPLOADS_URL +
item.attributes.Imagem.data.attributes.url
}
alt="Imagem Produto"
/>
</div>
);
})}
</div>
</div>
);
};
export default CollectionsBar;
Parent Component:
import React, { useEffect } from "react";
import useFetch from "../../hooks/useFetch";
import CollectionsBar from "../../components/CollectionsBar/CollectionsBar";
import "./Products.scss";
const Products = () => {
return (
<div className="sl-c-products">
<div className="sl-l-products__flex">
<span></span>
</div>
<CollectionsBar />
</div>
);
};
export default Products;
I just want to know the best way of doing it...
答案1
得分: 2
你有两个选项:
-
提升状态。
这是更简单的方法。你只需要将状态移动到父组件,并将setter作为prop传递下来:
const Products = () => { const [collection, setCollection] = useState(); return ( <div className="sl-c-products"> <div className="sl-l-products__flex"> <span></span> </div> <CollectionsBar setCollection={setCollection} /> </div> ); }; export default Products;
然后在子组件中可以使用setter:
const CollectionsBar = ({ setCollection }) => { const { data, loading, error } = useFetch(""); return ( <div className="sl-c-collections-bar"> <div className="sl-l-bar__flex"> {minifyData?.map((item, index) => { return ( <div onClick={() => { setCollection(index); }} key={index} className="sl-c-flex__box" > <img //... /> </div> ); })} </div> </div> ); }; export default CollectionsBar;
如果需要在子组件中使用该状态,也可以将状态作为prop传递。
-
使用useRef和forwardRef hooks。
如果无法提升状态,你需要使用ref。对于这种情况,你需要对React的工作原理有一定的了解。
按照相同的示例:
创建一个ref(childStateRef),并将其作为prop传递给子组件。然后,使用ref可以调用在子组件中创建的函数。
const Products = () => { const childStateRef = useRef(null); console.log(childState.current.getCollection()); // 这将记录状态 return ( <div className="sl-c-products"> <div className="sl-l-products__flex"> <span></span> </div> <CollectionsBar ref={childStateRef} /> </div> ); };
在子组件中:
使用forwardRef包装组件,并使用"useImperativeHandle"创建一个函数来获取状态。
const CollectionsBar = forwardRef((props, _ref) => { const { data, loading, error } = useFetch(""); const [collection, setCollection] = useState(); useImperativeHandle(_ref, () => ({ getCollection: () => { return collection; }, })); return ( <div className="sl-c-collections-bar"> <div className="sl-l-bar__flex"> {minifyData?.map((item, index) => { return ( <div onClick={() => { setCollection(index); }} key={index} className="sl-c-flex__box" > <img //... /> </div> ); })} </div> </div> ); }); export default CollectionsBar;
英文:
You have two options:
-
Lifting up the state.
This is the simpler way to do it. You just need to move your state to the parent component, and pass the setter down as a prop:
const Products = () => { const [collection, setCollection] = useState(); return ( <div className="sl-c-products"> <div className="sl-l-products__flex"> <span></span> </div> <CollectionsBar setCollection={setCollection} /> </div> ); };
export default Products;
Then in the children you can use the setter:
const CollectionsBar = ({setCollection}) => {
const { data, loading, error } = useFetch("");
return (
<div className="sl-c-collections-bar">
<div className="sl-l-bar__flex">
{minifyData?.map((item, index) => {
return (
<div
onClick={() => {
setCollection(index);
}}
key={index}
className="sl-c-flex__box"
>
<img
//...
/>
</div>
);
})}
</div>
</div>
);
};
export default CollectionsBar;
You also can pass the state if you need to use it in the children component.
- Use the useRef and forwardRef hooks
If by any chance, you can't lift up the state, you need to use ref. For this alternative, you should understand a bit more about how React works.
Following the same example:
Create a ref(childStateRef) and pass it as a prop to the children. Then, using the ref, you can call the fn you will create in the children comp.
const Products = () => {
const childStateRef = useRef<any>(null);
console.log(childState.current.getCollection()) //this will log the state
return (
<div className="sl-c-products">
<div className="sl-l-products__flex">
<span></span>
</div>
<CollectionsBar ref={childStateRef} />
</div>
);
};
In your children component:
Wrap the component with forwardRef and use "useImperativeHandle" to create a function to get your state.
const CollectionsBar = forwardRef((props, _ref) => {
const { data, loading, error } = useFetch("");
const [collection, setCollection] = useState()
useImperativeHandle(_ref, () => ({
getCollection: () => {
return collection;
},
}));
return (
<div className="sl-c-collections-bar">
<div className="sl-l-bar__flex">
{minifyData?.map((item, index) => {
return (
<div
onClick={() => {
setCollection(index);
}}
key={index}
className="sl-c-flex__box"
>
<img
//...
/>
</div>
);
})}
</div>
</div>
);
});
export default CollectionsBar;
答案2
得分: 0
将 const [collection, setCollection] = useState();
从子组件移动到父组件,然后将其作为 prop 传递下去。
// 父组件
...
const [collection, setCollection] = useState();
return (
<CollectionsBar setCollection={setCollection}/>
)
....
// 子组件
const CollectionsBar = ({setCollection}) => {
// 现在你的状态在父组件中,但可以从子组件中更改它
}
英文:
Move const [collection, setCollection] = useState();
from the child to the parent component and then pass it down as a prop.
// Parent component
...
const [collection, setCollection] = useState();
return (
<CollectionsBar setCollection={setCollection}/>
)
....
// Child component
const CollectionsBar = ({setCollection}) => {
// now you have your state in a parent component but can change it from the child one
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论