#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 являются функциями обратного вызова и не работают, когда я использую функции со стрелками. Я попробую еще немного поиграть с этим. Спасибо за вашу помощь, поскольку это отвечает на прямой вопрос, который я задал, я принял ваш ответ. Поскольку я думаю, что начинаю отклоняться от темы исходного вопроса, я могу опубликовать новый, если не смогу разобраться 🙂