I am a beginner of React JS. Messing around to achieve VanJS event listeners.
For layout, I decide to store things like a panel, a button
as individual component.
Now, I have a component Movie
and another component Button
, how can I trigger state change of Movie by Button.onclick()?.
In other words, how to modify a component by the event happening on another component?
Before posting, I have read:
but tons of method followed by really confused me.
useState
componentWillMount
: immediately before initial renderingcomponentDidMount
: immediately after initial renderingcomponentWillReceiveProps
: when component receives new propsshouldComponentUpdate
: before rendering, after receiving new props or statecomponentWillUpdate
: before rendering, after receiving new props or state.componentDidUpdate
: after component's updates are flushed to DOMcomponentWillUnmount
: immediately before removing component from DOM
Following is a demo, which contains a Movie
card and a Button
, when the button is clicked, I want the background colour of the Movie card to change
the code:
import * as React from "react";import "./styles.css";import styled from 'styled-components';function CSSPropertiesToComponent(dict:React.CSSProperties){ let str = ''; for(const [key, value] of Object.entries(dict)){ let clo = ''; key.split('').forEach(lt=>{ if(lt.toUpperCase() === lt){ clo += '-'+ lt.toLowerCase(); }else{ clo += lt; } }); str += clo +':'+ value +';'; } return str;}class Movie extends React.Component<any, any>{ public static style:React.CSSProperties|object = { width: "300px", height: "120px", display: "flex", justifyContent: "space-around", alignItems: "center", borderRadius: "20px", filter: "drop-shadow(0px 1px 3px #6d6d6d)", WebkitFilter: "drop-shadow(3px 3px 3px #6d6d6d)", backgroundColor: '#'+Math.floor(Math.random()*16777215).toString(16), fontSize: '2.5rem', margin: '20px', color: '#fff', } props:React.ComponentProps<any>; state:React.ComponentState; constructor(props:any) { super(props); this.props = props; this.state = {style: Object.assign({}, Movie.style)} this.changeColor = this.changeColor.bind(this); } changeColor():void{ this.setState({style: Object.assign({}, Movie.style, {backgroundColor: '#'+Math.floor(Math.random()*16777215).toString(16)})}); } render():JSX.Element{ let StyledMovie = styled.div` ${CSSPropertiesToComponent(Movie.style)} `; return (<><StyledMovie>{this.props.title}</StyledMovie></> ) }}export default function App() { let MV = new Movie({title: 'the Avengers'}); return (<> {MV.render()}<button onClick={MV.changeColor}>Change Color</button></> )}
However, when clicking on the change colour button, it doesn't work and shows a warning:
Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the Movie component.
if anyone offers some suggestion, I will be so glad.