jdog
jdog

Reputation: 10759

this.props.location ends up being undefined in my component

In my reactJS app I am trying to get the query param but location is null?

 useEffect(() => {
    const query = new URLSearchParams(props.location.search).get('sound');
    console.log(`location is ${props.params}`);
    console.log('about to fetch product');

Could it be because in my route I am not setting up a query param? Or is it because I am running in dev mode on my localhost? FYI - I just randomly add ?sound=sdfsdf to the URL by typing in manually to the browser.

UPDATE ====

import React, { useState, useEffect, useRef } from 'react';
import { Link } from 'react-router-dom';
import { Row, Col, Image, ListGroup, Card, Button } from 'react-bootstrap';
import Rating from '../components/Rating';
import socketIOClient from 'socket.io-client';
import axios from 'axios';
// import Product from '../components/Product';
import dotenv from 'dotenv';
import { ReactMediaRecorder } from 'react-media-recorder';
import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/storage';
import { FaSpinner } from 'react-icons/fa';
import qs from 'query-string';
// import firebase from 'firebase';
// import 'firebase/firestore';
// import firebaseKeys from '../firebase.json';
// import admin from 'firebase-admin';
import Delayed from '../components/Delayed';
import crypto from 'crypto';
// import { CopyToClipboard } from 'react-copy-to-clipboard';
const ENDPOINT = 'http://localhost:5000';

const firebaseConfig = {
  apiKey: 'AIza_47lCzPY',
  authDomain: 'bueocorce.firebap.com',
  databaseURL: 'https://burrrce.firebaseio.com',
  projectId: 'burerce',
  storageBucket: 'burrce.appspot.com',
  messagingSenderId: '316448',
  appId: '1:1f5',
  measurementId: 'G-9N',
};

dotenv.config();
firebase.initializeApp(firebaseConfig);
// export const firestore = firebase.firestore();
export const storage = firebase.storage();
// firebase.analytics();

// const FireStoreStuff = () => {
//   const [firestore, fireStorage, setFirestore] = useState(undefined);

//   useEffect(() => {
//     firebase.initializeApp(firebaseKeys);
//     setFirestore(firebase.firestore(), firebase.storage());
//     // ...
//   }, []);
// };
const AudioPreview = ({ stream }) => {
  const audioRef = useRef(null);

  useEffect(() => {
    console.log('starting audioPreview ========');
    if (stream) audioRef.current.srcObject = stream;
  }, [stream]);

  if (!stream) return null;
  return <audio ref={audioRef} autoPlay controls />;
};

const VideoPreview = ({ stream }) => {
  const videoRef = useRef(null);

  useEffect(() => {
    console.log('starting audioPreview ========');
    if (stream) videoRef.current.srcObject = stream;
  }, [stream]);

  if (!stream) return null;
  return <video ref={videoRef} autoPlay controls />;
};

function copy(paramid) {
  const el = document.createElement('input');
  el.value = window.location.href;
  el.value = el.value + '?sound=' + paramid;
  document.body.appendChild(el);
  el.select();
  document.execCommand('copy');
  document.body.removeChild(el);
}
function Controls({ status, startRecording, stopRecording, mediaBlobUrl }) {
  const [copied, setCopied] = useState(false);
  const [url, setURL] = useState('');
  async function uploadFile() {
    console.log('starting UPLOAD ========');
    const blob = await fetch(mediaBlobUrl).then((r) => r.blob());
    var id = crypto.randomBytes(16).toString('hex');
    var url = window.location.href;
    console.log(` the unique id for the url is ----> ${id}`);
    const path = `/recordings/${id}`;
    copy(id);
    setCopied(true);
    firebase
      .storage()
      .ref(path)
      .put(blob)
      .then(function (snapshot) {
        console.log('Uploaded complete');
      });

    storage.ref(path).getDownloadURL().then(setURL);
  }
  return (
    <Row>
      {/* <span className='uk-text-meta'>{status}</span> */}
      <button className='uk-margin-small-left' type='button' onClick={startRecording} disabled={status === 'recording'}>
        Start
      </button>
      <button className='uk-margin-small-left' type='button' onClick={stopRecording} disabled={status === 'stopped'}>
        Stop
      </button>
      <Row>
        {status === 'recording' ? (
          <FaSpinner icon='spinner' className='spinner' />
        ) : (
          <button
            className='uk-margin-small-left'
            type='button'
            onClick={uploadFile}
            disabled={status !== 'stopped'}
            hidden={status === 'idle'}
          >
            {!copied ? 'Copy link' : 'Copied!'}
          </button>
        )}
      </Row>

      {/* <Delayed waitBeforeShow={10000}>
        <button className='uk-margin-small-left' type='button' onClick={uploadFile} disabled={status !== 'stopped'}>
          done
        </button>
      </Delayed> */}
      {url && (
        <a className='uk-margin-small-left' href={url} target='_blank' rel='noopener noreferrer'>
          open
        </a>
      )}
    </Row>
  );
}

function RecordAudio() {
  return (
    <ReactMediaRecorder
      audio
      render={({ status, startRecording, stopRecording, previewStream, mediaBlobUrl }) => (
        <Row>
          {status === 'recording' ? (
            <AudioPreview stream={previewStream} />
          ) : (
            <audio src={mediaBlobUrl} controls autoPlay />
          )}
          <Controls
            status={status}
            startRecording={startRecording}
            stopRecording={stopRecording}
            mediaBlobUrl={mediaBlobUrl}
          />
        </Row>
      )}
    />
  );
}

function RecordVideo() {
  return (
    <ReactMediaRecorder
      video
      render={({ status, startRecording, stopRecording, previewStream, mediaBlobUrl }) => (
        <Row>
          {status === 'recording' ? (
            <VideoPreview stream={previewStream} />
          ) : (
            <video src={mediaBlobUrl} controls autoPlay />
          )}
          <Controls
            status={status}
            startRecording={startRecording}
            stopRecording={stopRecording}
            mediaBlobUrl={mediaBlobUrl}
          />
        </Row>
      )}
    />
  );
}

// function RecordScreen() {
//   return (
//     <ReactMediaRecorder
//       screen
//       render={({ status, startRecording, stopRecording, mediaBlobUrl }) => (
//         <div>
//           <video src={mediaBlobUrl} controls autoPlay />
//           <Controls
//             status={status}
//             startRecording={startRecording}
//             stopRecording={stopRecording}
//             mediaBlobUrl={mediaBlobUrl}
//           />
//         </div>
//       )}
//     />
//   );
// }

// function handleClick(num) {
//   this.setState(num);
// }

const ProductScreen = ({ match }) => {
  const [product, setProduct] = useState({});
  // const query = null;

  // const query = URLSearchParams(props.location.search).get('sound');
  // console.log(this.match.location.search);
  // if (match && match.location && match.location.search) {
  //   query = qs.parse(match.location.search, {
  //     ignoreQueryPrefix: true,
  //   });
  // }

  useEffect(() => {
    const query = new URLSearchParams(match.location).get('sound');
    console.log(`location is ${match.params}`);
    console.log('about to fetch product');
    const fetchProduct = async () => {
      console.log('Below is the id param waht the fuck is it?');
      console.log(match.params.id);
      const { data } = await axios.get(`http://localhost:5000/api/products/${match.params.id}`);

      setProduct(data);
    };
    fetchProduct();
    const socket = socketIOClient(ENDPOINT);
    socket.on('status-update', function (call) {
      const stext = document.getElementById('statusText');
      stext.innerText = call;
    });

    // CLEAN UP THE EFFECT
    // return () => socket.disconnect();
  }, [match]);
  const [state, setState] = useState(0);
  return (
    <>
      <script src='https://www.gstatic.com/firebasejs/8.7.1/firebase-app.js'></script>

      <script src='https://www.gstatic.com/firebasejs/8.7.1/firebase-analytics.js'></script>
      <Link className='btn btn-light my-3' to='/'>
        Go Back
      </Link>
      <Row>
        <Col md={6}>
          <Image src={product.image} alt={product.name} fluid />
        </Col>
        <Col md={3}>
          <ListGroup variant='flush'>
            <ListGroup.Item>
              <h3>{product.name}</h3>
            </ListGroup.Item>
            <ListGroup.Item>
              <Rating value={product.rating} text={`${product.numReviews} reviews`} />
            </ListGroup.Item>
            <ListGroup.Item>Price : {product.price}</ListGroup.Item>
            <ListGroup.Item>Description : {product.description}</ListGroup.Item>
          </ListGroup>
        </Col>
        <Col md={3}>
          <Card>
            <ListGroup variant='flush'>
              <ListGroup.Item>
                <Row>
                  <Col>Price: </Col>
                  <Col>
                    <strong>${product.price}</strong>
                  </Col>
                </Row>
              </ListGroup.Item>
            </ListGroup>
            <ListGroup variant='flush'>
              <ListGroup.Item>
                <Row>
                  <Col>Status: </Col>
                  <Col>{product.countInStock > 0 ? 'In Stock' : 'Out of Stock'}</Col>
                </Row>
              </ListGroup.Item>
              <ListGroup.Item>
                <Button
                  //   onClick={addToCartHandler}
                  className='btn-block w-100'
                  type='button'
                  disabled={product.countInStock === 0}
                >
                  Add To Cart
                </Button>
              </ListGroup.Item>
              <ListGroup.Item>
                <Row>
                  <Col>Copy Status: </Col>
                  <Col>
                    <h2 id='statusText'>Share</h2>
                    <button type='button' onClick={() => setState(1)}>
                      audio
                    </button>
                    <button type='button' onClick={() => setState(2)}>
                      video
                    </button>
                    {/* <button type="button" onClick={() => setState(3)}>
        screen
      </button> */}
                    {state === 1 && <RecordAudio />}
                    {state === 2 && <RecordVideo />}
                    {/* {state === 3 && <RecordScreen />} */}
                  </Col>
                </Row>
              </ListGroup.Item>
            </ListGroup>
          </Card>
        </Col>
      </Row>
    </>
  );
};

export default ProductScreen;

Upvotes: 1

Views: 938

Answers (1)

Drew Reese
Drew Reese

Reputation: 202791

Issue

The match prop doesn't have a location property.

A match object contains information about how a <Route path> matched the URL. match objects contain the following properties:

  • params - (object) Key/value pairs parsed from the URL corresponding to the dynamic segments of the path
  • isExact - (boolean) true if the entire URL was matched (no trailing characters)
  • path - (string) The path pattern used to match. Useful for building nested <Route>s
  • url - (string) The matched portion of the URL. Useful for building nested <Link>s

The ProductScreen is only destructuring the match prop.

const ProductScreen = ({ match }) => { ....

Solution

Destructure the location prop and access the search property.

const ProductScreen = ({ location, match }) => {
  const [product, setProduct] = useState({});
  
  const query = new URLSearchParams(location.search).get('sound');
  console.log(location.search);

Upvotes: 2

Related Questions