Как передать данные от родителя к потомку в ReactJS после рендеринга компонентов

#javascript #reactjs #websocket

#javascript #reactjs #websocket

Вопрос:

Я провел много поисков и, похоже, не могу найти ответ на этот вопрос — возможно, я просто не использую правильную терминологию.

Что мне нужно сделать, это передать данные из компонента WebSocket в дочерний компонент. Я уже передаю WebSocket через props дочернему элементу, чтобы он мог использовать функцию send() и отправлять данные в сокет. Мне также нужно передать любые полученные данные через onmessage. Настройка обычным способом внутри дочернего элемента не работает.

Что мне нужно, так это когда данные получены в сокете, они отправляются дочернему элементу с функцией внутри дочернего элемента, чтобы затем что-то с ним сделать (отправить его через MIDI с использованием Web MIDI API)

Родительский

 class Socket extends Component {
  constructor(props) {
    super(props);
    this.state = {
      ws: null,
    };
  }

  componentDidMount() {
    this.connect();
  }
  
  connect = () => {
    var ws = new WebSocket("ws://127.0.0.1:8000/ws/");

    ws.onopen = () => {
      this.setState({ ws: ws });    
    };

    ws.onmessage = (e) => {
      const data = JSON.parse(e.data);
      var midi = data["command"]; // Need to send this to the child somehow.
    };

    ......
}

  render() {
    return <MIDIComponent websocket={this.state.ws} />;
  }
}
  

РЕДАКТИРОВАТЬ: Итак, мне удалось получить данные от родителя к потомку, и я отобразил их на экране для тестирования. Но я не могу извлечь их внутри нужных мне функций. Я пробовал комбинации использования функций со стрелками, привязки ‘this’ и т.д. Я либо не могу получить доступ к этому, либо midi-порты возвращаются как undefined или null, значение по умолчанию.

Дочерний

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

    this.state = {
      midiInput: null,
      midiOutput: null,
    };
  }
  componentDidMount() {
    const that = this;
    this.setupMIDI(that);
  }

  setupMIDI = (that) => {
    navigator.requestMIDIAccess({ sysex: true }).then(onMIDISuccess);

    function onMIDISuccess(midiAccess) {
      that.setState({ midiInput: Array.from(midiAccess.inputs.values())[0] });
      that.setState({ midiOutput: Array.from(midiAccess.outputs.values())[1] });
      that.state.midiInput.onmidimessage = getMIDIMessage;
// storing the midi ports in the state like this, but it doesnt work.
    }

    function getMIDIMessage(msg) {
      console.log(msg.data);
      that.props.websocket.send(
        JSON.stringify({ message: Array.from(msg.data), type: "config" })
      );
    }
  };

  sendMIDIMessage = (msg) => {
    this.state.midiOutput.send(msg); // need to get to the midiOutput port here to send the data
  };

  render() {
    return <div key={this.props.midi}>{this.props.midi}</div>; // Just using this to render the data to the screen for testing
  }
}

  

Вероятно, я должен упомянуть, что в конечном итоге у меня будет два дочерних компонента, которым необходимо будет получать данные из сокета в зависимости от типа полученных данных. На данный момент я просто хотел бы настроить его с помощью одного. Любая помощь была бы высоко оценена.

Комментарии:

1. Я не думаю, что вам нужно that . Что вы можете сделать, создайте отдельную функцию getMIDIMessage и sendMIDIMessage так же, как вы сделали для setupMIDI . Затем для каждой функции на том же уровне вы либо устанавливаете состояния для какой-либо конкретной логики, либо получаете реквизиты для того же this

2. Если вы обновите состояние, react отобразит его снова. Просто сохраните данные в состоянии.

3. Хорошо, я попробую это, спасибо, а затем я просто передам это через props так же, как я уже?

Ответ №1:

Просто сохраните полученные данные в таком состоянии, как это:

 
class Socket extends Component {
  constructor(props) {
    super(props);
    this.state = {
      ws: null,
      midi: [] // Create an empty array so that the child always received something and not undefined
    };
  }

  componentDidMount() {
    this.connect();
  }
  
  connect = () => {
    var ws = new WebSocket("ws://127.0.0.1:8000/ws/");

    ws.onopen = () => {
      this.setState({ ws: ws });    
    };

    ws.onmessage = (e) => {
      const data = JSON.parse(e.data);
      const midi = data["command"]; // Need to send this to the child somehow.
      this.setState({
        midi // Save the received data in the state
      });
    };

}

  render() {
    const {ws, midi} = this.state; // Extract the data from the state
    return <MIDIComponent websocket={ws} midi={midi}/>; // Pass the data as a prop to the child
  }
}
  

Комментарии:

1. Спасибо, да, я зашел так далеко, хотя немного по-другому я могу теперь передавать данные в дочерний компонент, и я просто рендерю их внутри <div>. Проблема, с которой я сталкиваюсь сейчас, заключается в том, чтобы извлечь их из моих дочерних вложенных функций и передать их в функцию, которая мне нужна для ее использования.

2. Вы можете просто использовать this.props для доступа к вставленным данным в любом месте этого компонента.

3. Я думаю, что проблема, с которой я сталкиваюсь, заключается в том, что «это» продолжает возвращаться неопределенным. Я пытался привязать его, используя функции со стрелками и т.д., Но не работает. Итак, мне нужно использовать порт промежуточного вывода, который создается из обратного вызова requestMIDIAccess success, я попытался сохранить это в состоянии, а затем получить к нему доступ оттуда повсюду. Мне также нужна функция для отправки MIDI-данных каждый раз, когда обновляется MIDI-реквизит. Я отредактировал свой вопрос, чтобы показать, что я делаю, если бы вы могли взглянуть? Я думаю, что большая часть проблемы исходит от MIDI API.

4. Хорошо, вам не нужно передавать то или иное в вашей функции. Используйте функции со стрелками вместо ключевого слова function, и это работает так, как ожидалось. Поскольку ключевое слово function не передает функции внешнее this, а вместо этого создает новую ссылку this (сама функция). Поэтому попробуйте удалить ключевое слово function и посмотрите, работает ли это для вас.

5. Да, я пробовал, я думаю, проблема в том, что getMIDIMessage и onMIDISuccess являются функциями обратного вызова и не работают, когда я использую функции со стрелками. Я попробую еще немного поиграть с этим. Спасибо за вашу помощь, поскольку это отвечает на прямой вопрос, который я задал, я принял ваш ответ. Поскольку я думаю, что начинаю отклоняться от темы исходного вопроса, я могу опубликовать новый, если не смогу разобраться 🙂