Search code examples
phpreactjslaravelbroadcasting

laravel broadcasting - client receives one response several times


I was creating a simple real time chat application (laravel, reactjs,pusher).

The server just get name AND text message from client (ReactJs), stores data in database and then pass the new data to my event and event pass it to client.

It works but my problem is listener in client receives data for several times and the counts of receiving data get more after each request.
I just want to get data from server one time.

my controller:

class MessageController extends Controller
{
    public function index(Request $request){
       $message = Message::create([
        'name' => $request->name,
        'text' => $request->text
      ])->toArray();

     return event(new MessageEvent($message));
    }
}

my event:

class MessageEvent implements ShouldBroadcast
{
  use SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public $data;
    public function __construct($message)
    {
        $this->data = $message;

    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn(){
       return 'messages';
    }

    public function broadcastAs(){
        return 'MessageEvent';
    }

    public function broadcastWith(){
    return  [
        'id' => $this->data['_id'],
        'name' => $this->data['name'],
        'text' => $this->data['text']
      ];
    }
}

My client side chat room:

export function ChatPage({ dispatch, getMessages, sendMessage, chatPage }) {
  useInjectReducer({ key: 'chatPage', reducer });
  useInjectSaga({ key: 'chatPage', saga });
  const [text, setText] = useState('');

  window.Echo = new Echo({
    broadcaster: 'pusher',
    key: '8171e9879fae800e8fef',
    cluster: 'ap2',
    forceTLS: true,
  });

  const channel = window.Echo.channel('messages');
  channel.listen('.MessageEvent', function(data) {
    console.log(data, 'index');
  });

  return (
    <ChatWrapper>
      <Helmet>
        <title>ChatPage</title>
        <meta name="description" content="Description of ChatPage" />
      </Helmet>
      <div className="container">
        {chatPage.data
          ? chatPage.data.map(item => (
              <div
                className={
                  item.name === localStorage.getItem('chat')
                    ? 'item-rigth'
                    : 'item-left'
                }
                key={item.id}
              >
                <span>
                  {item.name}
                  <hr />
                  {item.text}
                </span>
              </div>
            ))
          : null}
        <div className="form">
          <div>
            <input
              type="text"
              value={text}
              onChange={e => setText(e.target.value)}
              placeholder="Type Something..."
            />
            <img
              src={Send}
              onClick={() => {
                sendMessage(text);
                setText('');
              }}
            />
          </div>
        </div>
      </div>
    </ChatWrapper>
  );
}

ChatPage.propTypes = {
  dispatch: PropTypes.func.isRequired,
};

const mapStateToProps = createStructuredSelector({
  chatPage: makeSelectChatPage(),
});

function mapDispatchToProps(dispatch) {
  return {
    dispatch,
    sendMessage: text => dispatch(messageAction(text)),
    getMessages: data => dispatch(messageSuccessAction(data)),
  };
}

const withConnect = connect(
  mapStateToProps,
  mapDispatchToProps,
);

export default compose(
  withConnect,
  memo,
)(ChatPage);

I think when I call event from postman it works correctly but when I request to server from my client it give response several times (I think that is for re rendering the page).

what should I do exactly?


Solution

  • hey i solved the problem :).

    i put my listener section into to the useEffect:

      useEffect(() => {
        window.Echo = new Echo({
          broadcaster: 'pusher',
          key: '8171e9879fae800e8fef',
          cluster: 'ap2',
          forceTLS: true,
        });
        const channel = window.Echo.channel('messages');
        channel.listen('.MessageEvent', function(data) {
          console.log(data, 'data');
        });
      }, []);