1

I am using React Context in order to manage a global state.

So I have defined my Context with its Provider and its Consumer.

I have my videoplaying-context.js

import React from "react";
import { createContext } from 'react';

// set the defaults
const VideoContext = React.createContext({
  videoPlaying: false,
  setPlayingVideo: () => {}
});

export default VideoContext;

In my _app.js I have:

import App from 'next/app'
import { PageTransition } from 'next-page-transitions'
import VideoContext from '../components/videoplaying-context'

class MyApp extends App {
  setPlayingVideo = videoPlaying => {
    this.setState({ videoPlaying });
  };

  state = {
    videoPlaying: false,
    setPlayingVideo: this.setPlayingVideo
  }
  render() {
    console.log('new _app.js defalt page');
    const { Component, pageProps, router, state } = this.props
    return (
      <React.Fragment>
        <VideoContext.Provider value={this.state}>
          <PageTransition timeout={300} classNames="page-transition">
            <Component {...pageProps} key={router.route} />
          </PageTransition>
        </VideoContext.Provider>
      </React.Fragment>
    )
  }
}

export default MyApp

and then in one of my file I have put the Consumer:

import Layout from "../components/Layout";
import ReactPlayer from 'react-player
import VideoContext from '../components/videoplaying-context'

class Video extends React.Component {
  constructor(props) {
    super(props);
    this.triggerVideo = this.triggerVideo.bind(this);
  }
  triggerVideo(event) {
    console.log("click");
    /* doing other stuff here... */
  }
  render() {
    return (
      <VideoContext.Consumer>
        {context => (
          <Layout>
            <h1>Videos</h1>
            <div>
              <div className="group" id="process-video">
                <div
                  className="poster-image"
                  onClick={() => {
                    this.triggerVideo.bind(this);
                    context.setPlayingVideo(true);
                  }}
                />
                <ReactPlayer
                  url="https://vimeo.com/169599296"
                  width="640px"
                  height="640px"
                  config={{
                    vimeo: {
                      playerOptions: {
                        thumbnail_url: "http://placehold.it/640x640.jpg",
                        thumbnail_width: 640,
                        thumbnail_height: 640
                      }
                    }
                  }}
                />
              </div>
            </div>
            <style jsx global>{`
              .group {
                position: relative;
                height: 0;
                overflow: hidden;
                height: 640px;
                width: 640px;
              }

              .poster-image {
                background: url("http://placehold.it/640x640.jpg") center center;
                background-size: cover;
                bottom: 0;
                left: 0;
                opacity: 1;
                position: absolute;
                right: 0;
                top: 0;
                z-index: 10;
                height: 640px;
                width: 640px;
                transition: all 0.4s ease-in;
              }

              .poster-image + div {
                position: absolute;
                top: 0;
                left: 0;
                width: 640px;
                height: 640px;
              }

              .poster-image.video--fadeout {
                opacity: 0;
              }
            `}</style>
          </Layout>
        )}
      </VideoContext.Consumer>
    );
  }
}

export default Video;

So, the function "context.setPlayingVideo(true)" is working fine and it's correctly setting the global state "videoPlaying" to true, but, after the introduction of the Context, "this.triggerVideo.bind(this);" is not working anymore because "this" is undefined.

I tried removing it and other stuff but I'm really stuck and I don't know hot to fix it.

Thanks everyone!

keikai
  • 14,085
  • 9
  • 49
  • 68
Alessio
  • 3,404
  • 19
  • 35
  • 48
  • 3
    `onClick={() => {this.triggerVideo.bind(this);` here you're not calling it, you're just creating a bound function and doing nothing with it. – Emile Bergeron Mar 19 '20 at 18:36
  • Does this answer your question? [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – Emile Bergeron Mar 19 '20 at 18:36
  • 1
    Specifically, check the [documentation on `bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind) and while you're on MDN, check `apply` and `call`, they will help you understand how the JS context works. – Emile Bergeron Mar 19 '20 at 18:38

1 Answers1

2

On this line you are not calling the method triggerVideo

onClick={() => { this.triggerVideo.bind(this); context.setPlayingVideo(true); }}

Change to:

onClick={() => { this.triggerVideo(); context.setPlayingVideo(true); }}

or to:

onClick={() => { this.triggerVideo.bind(this)(); context.setPlayingVideo(true); }}
Kevyn Klava
  • 316
  • 1
  • 7