Я пытаюсь отобразить две разные строки из 2 разных вызовов API в одном и том же компоненте

#javascript #reactjs

Вопрос:

 import { useState, useEffect } from 'react';
import socketConnection from '../../connection';
import NavBar from '../../../Component/NavBar.';

const ws = socketConnection();

export default function GetEvent() {
  const [matchTime, setMatchTime] = useState('');
  const [teamNames, setTeamNames] = useState('');
  const [market, setMarket] = useState('');
  const [isLoading, setLoading] = useState(true);
  const [socketData, setSocketData] = useState([]); // array of objects.



useEffect(() => {
    ws.onopen = () => ws.send(
      /* eslint-disable */
        JSON.stringify({
          keys: ['xyz'],
          type: 'getEvent',
          id: 111,
          keys: ['skd'],
          type: 'getMarket',
          id: 222,
        }),
      );
function handleMessage(event) {
  console.log('Handling message');
  setLoading(true);
  const parsedData = JSON.parse(event.data);
  console.log(parsedData);
  setMatchTime(parsedData.data.startTime);
  setTeamNames(parsedData.data.name);
  setSocketData((currentSocketData) => [...currentSocketData, parsedData]);
  setMarket((currentSocketData) => [...currentSocketData, parsedData[1]]);
  setLoading(false);
}
    ws.addEventListener('message', handleMessage);

    return () => ws.removeEventListener('message', handleMessage);
  }, []);
 

@консоль разработчиков

console.log(matchTime); массив неопределенных объектов.ожидается ‘2020 09 02’
console.log(teamNames); в полдень/полный рабочий день-ожидается ‘рейнджеры против волков’
console.log(market); массив неопределенных объектов.ожидается ‘Перерыв/полный рабочий день’

Я также пробовал визуализировать как разные компоненты, но это не имеет смысла, так как это просто строки из API.

 return (
    <>
      <NavBar />
      <div className="footyevent" data-testid="footy-event-id">
        <div className="container">
          <h1>Football</h1>
          <div className="title-box">
            {isLoading amp;amp; <div className="loading">Not Connected... Please 
             Refresh</div>}
          </div>
          <div className="title-box">
            <div className="startTime" data-testid="event-time-id">
              Date amp; Time: {matchTime}  {/* blanc */}
            </div>
          </div>
          <div className="title-box">
            <div className="teams" data-testid="playing-teams-id">
              {teamNames}  {/* HalfTime/FullTime */}
            </div>
          </div>
          <div className="title-box">
            <div className="socket-data" data-testid="socket-data-id">
              {socketData.map((x, index) => (
                <p>
                  {x.data.name}  {/* HalfTime/FullTime */}
                </p>
              ))}
            </div>
          </div>
        </div>
      </div>
    </>
  );
}
 

Behaviour is fine with a single API call of

 JSON.stringify({
          keys: ['xyz'],
          type: 'getEvent',
          id: 212,
        }),
      );
 

update: I’m finding it difficult now to resolve or map over the data(objects) received from the WebSocket server response.

 export default function GetEvent() {
  const [isLoading, setLoading] = useState(true);
  const [socketData, setSocketData] = useState([]); // objects.

  useEffect(() => {
    ws.onopen = () => {
      ws.send(
        /* eslint-disable */
        JSON.stringify({
          keys: ['xyz'],
          type: 'getEvent',
          id: 111,
        }),
      );
      ws.send(
        /* eslint-disable */
        JSON.stringify({
          keys: ['skd'],
          type: 'getMarket',
          id: 222
        }),
      );
    };


    function handleMessage(event) {
      console.log('Handling message');
      setLoading(true);
      const parsedData = JSON.parse(event.data);
      console.log(parsedData);
      setSocketData((currentSocketData) => [...currentSocketData, parsedData]);
      setLoading(false);
    }

    ws.addEventListener('message', handleMessage);

    return () => ws.removeEventListener('message', handleMessage);
  }, []);



socketData.forEach(x => x.forEach(y => {
    if (x.type === 'EVENT_DATA') {
      console.log(`event data: ${y.data.name}`);
    } else if (x.type === 'BET_DATA') {
      console.log(y.data.name);
    }
  }));
  

return (
    <>
      <div className="title-box">
    <div key="uniqueId2" className="teams" data-testid="playing-teams-id">
      {socketData.map(data1 => console.log(data1))}
    </div>
</div>
    </>
  );
}
 

Данные и ошибки консоли

перебор данных сокета, зарегистрированных:

 Uncaught TypeError: x.forEach is not a function
 

console.log(данные 1):

 {type: 'EVENT_DATA', data: {…}}
data: {
  id: 1;
  name: 'A';
  date: '12020507'
}
{type: 'MARKET_DATA', data: {…}}
data: {
  id: 1;
  name: 'Final Result';
}
 

console.log(данные 1[0])

 undefined
 

консоль.журнал(data1.name):

 'A'
'Final Result'
 

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

1. Какой ответ вы получаете, когда отправляете массив объектов и массив объектов в JSON.stringify?

2. Это может быть связано с тем фактом, что у вас есть дубликаты ключей в json, которые вы отправляете. Затем, когда вы пытаетесь проанализировать его, вы получаете неопределенные значения. Попробуйте отправить json с уникальными ключами.

3. да, это @Giovanni. Мне просто нужно разрешить/сопоставить ответ полученного объекта сейчас.

Ответ №1:

Ваша главная проблема, вероятно, в том,:

 JSON.stringify({
  keys: ['xyz'],
  type: 'getEvent',
  id: 111,
  keys: ['skd'],
  type: 'getMarket',
  id: 222,
})
 

Если вы используете дубликаты ключей в объектных литералах, они переопределят предыдущее значение.

 ({ a: 1, b: 2, c: 3, a: 4, b: 5 }) //=> { a: 4, b: 5, c: 3 }
 

Это означает, что значение первых 3 ключей (ключи, тип и идентификатор) будет потеряно.

Я не знаю, чего ожидает ваша розетка. Если он принимает массивы, вам следует вместо этого использовать следующее.

 ws.send(JSON.stringify([{
  keys: ['xyz'],
  type: 'getEvent',
  id: 111,
}, {
  keys: ['skd'],
  type: 'getMarket',
  id: 222,
}]))
 

В качестве альтернативы вы можете отправить 2 отдельных запроса.

 ws.send(JSON.stringify({
  keys: ['xyz'],
  type: 'getEvent',
  id: 111,
}))
ws.send(JSON.stringify({
  keys: ['skd'],
  type: 'getMarket',
  id: 222,
}))
 

Для этого последнего вам, возможно, придется настроить handleMessage функцию. Потому что вместо того, чтобы оба результата были в одном ответе, обработчик будет вызван 2 раза.

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

1. спасибо, @3limin4t0r Я подумал, что могу отправить 2 отдельных запроса, но моя проблема заключается в том, чтобы разрешить полученные данные WebSocket, поскольку они пришли в виде объектов, и я не смог сопоставить их. Я попробовал socketData.forEach(x => x.forEach(y => { if (x.type === 'EVENT_DATA') { console.log( данные о событиях: ${y.data.name} ); } else if (x.type === 'BET_DATA') { console.log(y.data.name); } })); Но я получил Uncaught TypeError: x.forEach is not a function

2. @saint Не могли бы вы поделиться структурой, которую вы получаете обратно? Текущая ошибка говорит вам , что socketData у вас нет функции forEach , что означает, что это не массив.

3. да, @3limin4t0r. в цепочке нет необходимости, так как x-это объект, а не массив. Так что итерации на socketData просто достаточно.

Ответ №2:

Это мой ответ, любезный рефакторинг

 export default function GetEvent() {
  const [socketData, setSocketData] = useState([]);

  useEffect(() => {
    ws.onopen = () => {
      ws.send(
      );
      ws.send(
      );
    };


    function handleMessage(event) {
      
    }

    ws.addEventListener('message', handleMessage);

    return () => ws.removeEventListener('message', handleMessage);
  }, []);





const myDom1 = socketData.map((dataObject, index, arr) => {
    if (dataObject.type === 'event-data') {
      return dataObject.data.startTime
    } 
  })
  const myDom2 = socketData.map((dataObject, index, arr) => {
    if (dataObject.type === 'market') {
      return dataObject.data.name
    } 
  })
  const myDom3 = socketData.map((dataObject, index, arr) => {
    same...

    } 
  })



return (
    <>
     <div className="t-b">
            <div key="uniqueId1" className="teams" data-testid="">
              <p>{myDom1}</p>
            </div>
          </div>
          <div className="t-b">
            <div key="uniqueId2" className="teams" data-testid="">
              <p>{myDom2}</p>
            </div>
          </div>
          <div className="t-b">
            <div key="uniqueId3" className="" data-testid="">
              <p>{myDom3}</p>
            </div>
          </div>
    </>
  );
}
 

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

1. Пожалуйста, добавьте дополнительные сведения, чтобы расширить свой ответ, например, ссылки на рабочий код или документацию.