【问题标题】:React: Build Connections Among ComponentReact:在组件之间建立连接
【发布时间】:2020-12-28 11:37:00
【问题描述】:

我是 React JS 的初学者。为实现 VanJS 事件侦听器而胡闹。

对于布局,我决定将 a panel, a button 之类的内容存储为单独的组件。

现在,我有一个组件Movie 和另一个组件Button,如何通过Button.onclick() 触发Movie 的状态更改?

换句话说,如何通过另一个组件上发生的事件来修改一个组件?

发帖前,我已阅读:

但是接下来的大量方法真的让我很困惑。

  • useState
  • componentWillMount: 在初始渲染之前
  • componentDidMount: 初始渲染后立即
  • componentWillReceiveProps: 当组件收到新的 props 时
  • shouldComponentUpdate: 渲染前,收到新的道具或状态后
  • componentWillUpdate: 渲染前,收到新的道具或状态后。
  • componentDidUpdate: 组件更新刷新到 DOM 后
  • componentWillUnmount: 在从 DOM 中移除组件之前

以下是一个演示,其中包含一个Movie 卡和一个Button,当单击按钮时,我希望电影卡的背景颜色发生变化

React TypeScript Code Sandbox

代码:

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>
        </>
    )
}

但是,当点击更改颜色按钮时,它不起作用并显示警告:

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.

如果有人提出建议,我会很高兴的。

【问题讨论】:

  • 这并没有以最好的方式回答您的问题,但它显示了一个非常基本的示例,该示例使用从父级到子级共享数据的函数组件。 https://stackblitz.com/edit/react-tswfof

标签: reactjs typescript react-native react-tsx


【解决方案1】:
let MV = new Movie({title: 'the Avengers'});
    return (
        <>
            {MV.render()}
            <button onClick={MV.changeColor}>Change Color</button>
        </>
    )

应该看起来像(使用 jsx 或 tsx):


onChangeColor(color) {
  setState({color: color}); // state won't be in Movie component !
}

// use React.Fragment if you don't want an additional div
return (
  <div>
    <Movie title={'the Avengers'} />
    <button onClick={onChangeColor}>Change Color</button>
  <div/>
)

同样在class Movie extends React.Component&lt;any, any&gt;,您将两个通用参数设置为any,第一个是组件“props”的类型(输入和回调),第二个是“state”的类型组件。


interface MovieProps {
  // ...
}

interface MovieState {
  // ...
}

class Movie extends React.Component<MovieProps, MovieState> { }

如前所述,查看您的代码,您需要将状态保存在 Movie 组件之外,您可能希望保持 App 组件干净,并制作另一个组件来包装 Moviebutton,这将负责处理两者之间的交互。

关于这段代码还有很多话要说,但我无法涵盖所有​​内容,我建议你按照教程来获得更强大的 React 基础知识。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-12
    • 2013-10-10
    • 2023-03-22
    • 2015-02-09
    • 2021-05-29
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    相关资源
    最近更新 更多