【问题标题】:How to re-render React Component when outside function is called?调用外部函数时如何重新渲染 React 组件?
【发布时间】:2019-06-28 14:37:24
【问题描述】:

我希望能够接收 mqtt 消息并将其显示在 Web 应用程序上。我正在使用 AWS Amplify 的 PubSub,函数调用发生在类组件之外。我无法直接从外部函数访问任何实例函数/属性,但我需要一些方法来触发 setState 更改,以便可以重新渲染 Web 应用程序,对吗?

我尝试直接从 React 类调用函数,但仍然没有发生重新渲染。我尝试制作一个外部变量,将收到的消息存储在其中,然后从 React 类访问该变量,但仍然没有触发器。然后我进行了研究,发现我可以每隔几秒钟强制重新渲染一次,但读到应该避免这样做。我应该使用 ComponentDidMount 和 setState 函数,但并不真正了解如何使其工作。

再次,我真正想做的就是获取消息并更新网络应用程序以显示新消息。听起来很简单,但我卡住了。

import...

var itemsArr = [];

function subscribe() {
    // SETUP STUFF
    Amplify.configure({
        ...
    });
    Amplify.addPluggable(new AWSIoTProvider({
        ...
    }));

    // ACTUAL SUBSCRIBE FUNCTION
    Amplify.PubSub.subscribe('item/list').subscribe({
        next: data => {
        // LOG DATA
        console.log('Message received', data);

        // GET NAMES OF ITEMS
        var lineItems = data.value.payload.lineItems;
        lineItems.forEach(item => itemsArr.push(item.name));
        console.log('Items Ordered', itemsArr);

        // THIS FUNCTION CALL TRIGGERS AN ERROR
        // CANT ACCESS THIS INSTANCE FUNCTION
        this.update(itemsArr);
    },
        error: error => console.error(error),
        close: () => console.log('Done'),
    });
}

// REACT COMPONENT
class App extends Component {
    constructor(props){
        super(props);

        this.state = {
            items:null,
        };
    }

    // THOUGHT I COULD USE THIS TO UPDATE STATE
    // TO TRIGGER A RE-RENDER
    update(stuff){
        this.setState({items: stuff});
    }

    render() {
        // THINK SUBSCRIBE METHOD CALL SHOULDN'T BE HERE
        // ON RE-RENDER, KEEPS SUBSCRIBING AND GETTING
        // SAME MESSAGE REPEATEDLY
        subscribe();
        console.log('items down here', itemsArr);

        return (
            <div className="App">
                <h1>Test</h1>
                <p>Check the console..</p>
                <p>{itemsArr}</p>
            </div>
        );
    }
}
export default App;

理想情况下,我希望在消息进入时显示项目列表的列,但我目前遇到错误 - “TypeError: Cannot read property 'update' of undefined”,因为订阅函数在类无权访问类内部的更新函数。

【问题讨论】:

  • 对于初学者,您尝试在对象实例之外调用实例方法。您只能在 App 类中调用 update()。

标签: javascript reactjs publish-subscribe aws-amplify


【解决方案1】:

将订阅方法放在 App 组件中,以便您可以调用它。您可以在 App 组件第一次渲染后调用 componentDidMount 生命周期中的 subscribe 方法来执行它(获取项目)。然后, update 方法将运行 this.setState() (将您的项目存储在状态中)导致 App 组件重新渲染。由于这种重新渲染,您的 this.state.items 将包含一些内容,并将显示在您的段落中。

class App extends Component {
  constructor(props){
    super(props);

    this.state = {
        items: [],
    };

    this.subscribe = this.subscribe.bind(this); 
    this.update = this.update.bind(this);
  }

  update(stuff){
    this.setState({ items: stuff });
  }

  subscribe() {
    // SETUP STUFF
    Amplify.configure({
      ...
    });
    Amplify.addPluggable(new AWSIoTProvider({
      ...
    }));

    // ACTUAL SUBSCRIBE FUNCTION
    Amplify.PubSub.subscribe('item/list').subscribe({
      next: data => {
      // LOG DATA
      console.log('Message received', data);

      // GET NAMES OF ITEMS
      let itemsArr = [];
      var lineItems = data.value.payload.lineItems;
      lineItems.forEach(item => itemsArr.push(item.name));
      console.log('Items Ordered' + [...itemsArr]);
      this.update(itemsArr);
    },
      error: error => console.error(error),
      close: () => console.log('Done'),
    });
  }

  componentDidMount() {
    this.subscribe();
  }

  render() {

    console.log('items down here ' + [...this.state.items]);

    return (
        <div className="App">
            <h1>Test</h1>
            <p>Check the console..</p>
            <p>{this.state.items !== undefined ? [...this.state.items] : "Still empty"}</p>
        </div>
    );
  }
}

export default App;

【讨论】:

  • 太棒了。谢谢。由于某种原因,当我最初尝试在组件中包含订阅功能时出现错误。但现在完美运行。谢谢
  • 没问题 :D 感谢您仍然接受我的回答。
猜你喜欢
  • 2019-11-22
  • 2020-09-29
  • 1970-01-01
  • 2020-06-06
  • 1970-01-01
  • 2021-06-19
  • 2018-04-22
  • 1970-01-01
相关资源
最近更新 更多