0

Hi I am making a Private chat Application In Livewire but the Thing is When i Insert a message don't show Unless I reload the Page please help me how can i resolved that ? thank u.

I am using Livewire Full-Page Components here is the Code

Note :- I am using this render function inside viewMessage function but data is not updated without page relaod.

this will load the all the conservation message

$this->render();

app\Http\Livewire\Messaging.php

 class Messaging extends Component
    {
        public $body;
        public $searchTerm;
        public $selectedUser;
    
        public function mount(){
    
                $this->selectedUser =User::where('id','!=',Auth::user()->id)
                                    ->first();
    
        }
    
        public function render()
        {
                $searchTerm = '%'.$this->searchTerm.'%';
                if($searchTerm){
                  $user=  User::where('id', '!=', Auth::user()->id)
                    ->where('user_type',1)
                    ->where('email', 'like', $searchTerm)
                    ->with('messages')
                    ->get();
                }
    
                $conservation = Message::query()
                    ->where('sender_id',  Auth::user()->id)
                    ->where('receiver_id',  $this->selectedUser->id)
                    ->orWhere('receiver_id',  Auth::user()->id)
                    ->where('sender_id', $this->selectedUser->id)
                    ->with('sender')
                    ->with('receiver')
                    ->get();
    
              return view('livewire.messaging',[
    
                 'users'         => $user,
                 'conservation'  =>$conservation
            ]);
        }
    
        public function viewMessages($userId){
    
             $this->selectedUser = User::findorFail($userId);
    
                 $senderExist = Message::where('sender_id',$this->selectedUser->id)->exists();
    
                if($senderExist){
                    $message = Message::where('sender_id',$this->selectedUser->id)->orderBy('receiver_id','Desc')->get();
                        foreach($message as $value){
                            $value->notification = "0";
                            $value->save();
                        }
                }
    
        }
    
        public function sendMessages(){
    
    
            Message::create([
                'receiver_id'           =>      $this->selectedUser->id,
                'sender_id'             =>      Auth::user()->id,
                'body'                  =>      $this->body,
    
            ]);
    
            $this->reset('body');
            $this->viewMessages($this->selectedUser->id);
            $this->render(); //this will load the all the conservation message
        }
    }

resources\views\livewire\messaging.blade.php

         <form wire:submit.prevent="sendMessages" action="#" >
                <div class="position-absolute bottom-0 col-md-12 pe-3">
                    <div class="input-group comment-box p-3">
                    <input wire:model.defer="body"    type="text" class="form-control" 
               placeholder="Type Message ..." aria-label="Aa" aria-describedby="button-addon2" required>
                    <button class="btn btn-outline-secondary py-0 px-3" type="submit" id="button-addon2"><i class='bx bx-send fs-4'></i></button>
                    </div>
                </div>
            </form>

2 Answers 2

2

I personally would not suggest loading in data on every single render. Livewire is able to hydrate previously fetched models and collections, which takes away the strain of reloading it from your database each render. I personally would write your component as such:

use Illuminate\Support\Collection;

class Messaging extends Component
{
    public $body = '';
    public $searchTerm = '';
    public $selectedUser;

    // Assuming you're using PHP 7.4 or above, else remove typehint
    public Collection $users; 
    public Collection $conversation;
  
    // Ensure we validate the data passed
    protected $rules = [
        'body' => ['required', 'string'],
    ];
  
    public function mount()
    {
        $this->selectedUser = User::where('id','!=',Auth::user()->id)->first();
      
        $this->getUsers();
        $this->getConversation();
    }
    
    public function render()
    {
        return view('livewire.messaging');
    }
  
    public function updated($field)
    {
        // Only update the users if the search term has changed
        if ($field === 'searchTerm') {
            $this->getUsers():
        }
    }

    public function viewMessages($userId)
    {
        $this->selectedUser = User::findorFail($userId);

        $senderExist = Message::where('sender_id',$this->selectedUser->id)->exists();

        if($senderExist) {
            $messages = Message::where('sender_id',$this->selectedUser->id)->orderBy('receiver_id','desc')->get();
            
            foreach($messages as $message){
                $message->notification = "0";
                $message->save();
            }
          
            // Are you saving the messages one by one to trigger model events? If not, use below query to instantly update all of them at once in the database:
          
//            Message::where('sender_id',$this->selectedUser->id)->orderBy('receiver_id','desc')->update([
//              'notification' => 0,
//            ]);
        }
    }

    public function sendMessages()
    {
        // Validate the data as per given rules
        $this->validate();

        Message::create([
            'receiver_id' => $this->selectedUser->id,
            'sender_id' => Auth::user()->id,
            'body' => $this->body,
        ]);

        $this->reset('body');
        $this->viewMessages($this->selectedUser->id);
        // Refresh conversation
        $this->getConversation();
    }
  
    public function getConversation()
    {
        $this->converstaion = Message::query()
          ->where('sender_id',  Auth::user()->id)
          ->where('receiver_id',  $this->selectedUser->id)
          ->orWhere('receiver_id',  Auth::user()->id)
          ->where('sender_id', $this->selectedUser->id)
          ->with('sender')
          ->with('receiver')
          ->get();
    }
  
    public function getUsers()
    {
        $query = User::where('id', '!=', Auth::user()->id)
          ->where('user_type', 1)
          ->with('messages');
      
      
        if (! empty($this->searchTerm)) {
            $searchTerm = '%'.$this->searchTerm.'%';
            $query->where('email', 'like', $searchTerm);
        }
      
        $this->users = $query->get();
    }
}

The render method gets called by Livewire itself each time something happens, such as a value change of a variable, or after a function was called. You should not call it yourself.

P.S. For Livewire to fully keep track of what is what, I suggest adding wire:key to data rows. For example, on a div that is holding the data to your conversation messages, add wire:key="message-{{$message->id}}". This way, if a data change happens, Livewire knows exactly what date should be changed. Read more about it here

Sign up to request clarification or add additional context in comments.

2 Comments

Actully few days ago my code was working perfectly with $this->render() but now it's not working . why is it not working now ?
Well then you must have made a change. Still, it's not suggested to call $this->render()
1

You should use the livewire emite event https://laravel-livewire.com/docs/2.x/events

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.