'How can I expose React Hook outside of my React Functional Component
I have a React Functional Component like this:
export const MyParentComponent = (props: Props) => {
const [myObjects, setMyObjects = React.useState< MyClass[] | undefined>(undefined);
//...
}
I have an array of 'MyClass' objects, in myObjects
and put that in the 'State' of React since that will affect MyParentComponent
rendering.
My question is how can I expose setMyObjects
method to class outside of MyParentComponent so that the caller can set a new array of MyObjects
and trigger a rendering of MyParentComponent ?
Solution 1:[1]
If you want the parent component to be able to change the state, you'd either
- Make
myObjects
a state of the parent component or - Initialize the
myObjects
state with the props passed from the parent component
Unless having the state inside the component prevents you from making your component a pure component, I'd typically recommend the latter:
const {
useState
} = React;
const MyComponent = (props) => {
const [myObjects, setMyObjects] = useState(props.myObjects)
return (
<div>Rendering from MyComponent
<ul>
{myObjects.map(o => <li>{o}</li>)}
</ul>
</div>
);
};
const MyParentComponent = () => {
const objects = ['object1 from MyParentComponent', 'object2 from MyParentComponent', 'object3 from MyParentComponent'];
return (<MyComponent myObjects={objects} />);
}
ReactDOM.render( <MyParentComponent / > ,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Solution 2:[2]
since you want to change the state of MyParentComponent
in outside of that component, that outside component need to be a child, since you can need to pass the setMyObjects
function as a prop. In other way you can you react feature called Context API
to access the state of a component which is not Descendant.
React Context API
This is a simple scenario that elaborates how to change the state of the parent component inside the child component by passing setState function as a prop to child.
const Movie = () => { // This is the Parent component which render movies.
const movies = [
{ id: 1, title: "Batman", ratings: 8 },
{ id: 2, title: "Avengers", ratings: 8 },
{ id: 1, title: "Dune", ratings: 9 }
];
const [myObjects, setMyObjects] = useState(movies);
return (
<div>
{myObjects.map((movie) => (
<p>{movie.title}</p>
))}
<ChangeMovie changeMovieList={setMyObjects}/> // This is the child component which handle changing the state of Movie(Parent). Here pass the state change function as a prop(changeMovieList) to child. Then we can use that to change the state inside that component.
</div>
);
};
export default Movie;
const ChangeMovie = (props) => { // This is the child component.
const changeList = () => {
props.changeMovieList([ // here we change the state of Movie(Parent Component) inside child using the function passed.
{ id: 1, title: "Superman", ratings: 8 },
{ id: 2, title: "Titanic", ratings: 8 },
{ id: 1, title: "Fast & Furious 8", ratings: 9 }
]);
};
return (
<>
<button onClick={changeList}>Change Movie List</button>
</>
);
};
export default ChangeMovie;
Check this demo sandbox I created to elaborate this.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | DevThiman |