-
-
Notifications
You must be signed in to change notification settings - Fork 27.2k
Description
Describe the bug
I have two pages, one called JobList and one called NewJob. In both pages I'm utilizing useState to initialize an array which I populate at mount time with the useEffect hook. Here is the error message I'm seeing when the app is deployed. It is clearly pointing to the places in the code where I'm using the map function on my arrays.
When I run using the development server with "npm start", via static build, or with a docker build command on my LOCAL machine everything works fine. However if I create an Ubuntu 18.04 VM and pull the Dockerfile, I'm getting the same result that my build pipeline is producing, which is the following error on the pages mentioned. I have a feeling there is some dependency which is not present on the remote build server causing this failure. However, issuing an "npm list -g --depth 0" returns the following which I wouldn't think would cause any interference.
/usr/lib
├── npm@6.14.5
├── package-diff@0.0.6
├── serve@11.3.2
├── webpack@4.43.0
└── webpack-cli@3.3.12
Did you try recovering your dependencies?
Yes, I have deleted the package-lock.json and node-modules folder and recreated the environment locally.
Environment
npx create-react-app --info output
npx: installed 98 in 3.783s
Environment Info:
current version of create-react-app: 3.4.1
running from /home/zach/.npm/_npx/12540/lib/node_modules/create-react-app
System:
OS: Linux 5.3 Ubuntu 18.04.4 LTS (Bionic Beaver)
CPU: (12) x64 AMD Ryzen 5 2600 Six-Core Processor
Binaries:
Node: 12.18.0 - /usr/bin/node
Yarn: 1.22.4 - /usr/bin/yarn
npm: 6.14.5 - /usr/bin/npm
Browsers:
Chrome: 83.0.4103.97
Firefox: 78.0.1
npmPackages:
react: ^16.13.1 => 16.13.1
react-dom: ^16.13.1 => 16.13.1
react-scripts: ^3.4.1 => 3.4.1
npmGlobalPackages:
create-react-app: Not Found
Error Messages
TypeError: i.map is not a function
at me (JobList.js:51)
at Wi (react-dom.production.min.js:153)
at ko (react-dom.production.min.js:175)
at gs (react-dom.production.min.js:263)
at cl (react-dom.production.min.js:246)
at sl (react-dom.production.min.js:246)
at Js (react-dom.production.min.js:239)
at react-dom.production.min.js:123
at t.unstable_runWithPriority (scheduler.production.min.js:19)
at Va (react-dom.production.min.js:122)
TypeError: f.map is not a function
at oe (NewJob.js:108)
at Wi (react-dom.production.min.js:153)
at ko (react-dom.production.min.js:175)
at gs (react-dom.production.min.js:263)
at cl (react-dom.production.min.js:246)
at sl (react-dom.production.min.js:246)
at Js (react-dom.production.min.js:239)
at react-dom.production.min.js:123
at t.unstable_runWithPriority (scheduler.production.min.js:19)
at Va (react-dom.production.min.js:122)
Javascript Code
NewJob.js:
import React, {useState, useEffect} from 'react';
import { useForm } from 'react-hook-form';
import Loading from "../components/Loading";
import { useAuth0 } from "../react-auth0-spa";
import { Form, Input, Alert } from 'reactstrap';
import API from "../utils/Api";
let S = require('string');
export default function NewJob() {
const { loading, user, getTokenSilently } = useAuth0();
const { register, handleSubmit, errors } = useForm();
const [filters, setFilters] = useState([]);
const [alert, setAlert] = useState({});
const [alertVisible, setAlertVisible] = useState(false);
const [page, setPage] = useState([1]);
const onDismiss = () => setAlertVisible(false);
useEffect(() => {
getTokenSilently()
.then(token => {
API.get(`/filters/?page=${page}`, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}})
.then(response => {
setFilters(response.data);
})
.catch(error => {
setAlert({
body: 'Unable to retrieve filters',
color: 'warning'
})
setAlertVisible(true);
});
})
}, [page]);
const onSubmit = async(data, e) => {
getTokenSilently()
.then(token => {
API.post('/jobs/', {
source_video_url: data.sourceVideoUrl,
selected_filter: data.filter,
email: data.email
},
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
})
.then(jsonResp => {
setAlert({
body: 'Job successfully submitted!',
color: 'success'
})
setAlertVisible(true);
})
.catch(error => {
setAlert({
body: 'Error, job was not submitted',
color: 'danger'
})
setAlertVisible(true);
})
})
};
const fieldOptions = {
'sourceVideoUrl': {
required: true,
pattern: {
value: /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})?$/i,
message: 'Invalid YouTube URL'
},
},
'filter': {
required: true
},
'email': {
required: true,
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
message: 'Enter a valid email address'
}
}
}
if (loading || !user) {
return <Loading />;
}
return (
<>
<Form onSubmit={handleSubmit(onSubmit)}>
<Input
type="text"
defaultValue="https://www.youtube.com/watch?v=qoLh9K5K5vc"
name="sourceVideoUrl"
innerRef={register(fieldOptions.sourceVideoUrl)}
invalid={errors.sourceVideoUrl}
/>
<br />
<Input type="select" name="filter" innerRef={register(fieldOptions.filter)}>
{filters.map(filter => (
<option value={filter.name}>{S(filter.name).capitalize().s}</option>
))}
</Input>
<br />
<Input type="text" defaultValue="zjpiazza@gmail.com" name="email" innerRef={register(fieldOptions.email)} invalid={errors.email} />
<br />
<Input type="submit" />
</Form>
<br />
<Alert color={alert.color} isOpen={alertVisible} toggle={onDismiss} >
{alert.body}
</Alert>
</>
);
}
JobList.js:
import React, {useState, useEffect} from 'react';
import { Table, Alert } from 'reactstrap';
import { useAuth0 } from "../react-auth0-spa";
import Loading from "../components/Loading";
import API from "../utils/Api";
let S = require('string');
export default function JobList (props) {
const { loading, user, getTokenSilently } = useAuth0();
const [jobs, setJobs] = useState([]);
const [page, setPage] = useState([1]);
const [alert, setAlert] = useState({});
const [alertVisible, setAlertVisible] = useState(false);
const onDismiss = () => setAlertVisible(false);
useEffect(() => {
getTokenSilently()
.then(token => {
API.get(`/jobs/?page=${page}`, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}})
.then(response => {
setJobs(response.data);
})
.catch(error => {
setAlert({
body: 'Error, unable to retrieve jobs',
color: 'danger'
})
});
})
}, [page, getTokenSilently]);
if (loading || !user) {
return <Loading />;
}
return (
<>
<Table striped>
<thead>
<tr>
<th>Job ID</th>
<th>Status</th>
<th>Download Link</th>
</tr>
</thead>
<tbody>
{jobs.map(job => (
<tr key={job.id}>
<th scope="row">{job.id}</th>
<td>{S(job.status).capitalize().s}</td>
<td>{job.download_link}</td>
</tr>
))}
</tbody>
</Table>
<br />
<Alert color={alert.color} isOpen={alertVisible} toggle={onDismiss} >
{alert.body}
</Alert>
</>
);
}
Dockerfile and Build Definition
Dockerfile:
# build environment
FROM node:14.5.0-alpine3.10 as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
RUN npm ci --silent --force
RUN npm install react-scripts@3.4.1 -g --silent
COPY . ./
RUN npm run build
# production environment
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
# new
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Azure DevOps build definition:
# Docker
# Build and push an image to Azure Container Registry
# https://docs.microsoft.com/azure/devops/pipelines/languages/docker
trigger:
- master
resources:
- repo: self
variables:
# Container registry service connection established during pipeline creation
dockerRegistryServiceConnection: '3919c5b1-8ce6-4f6c-aa87-73632208d6a2'
imageRepository: 'videoeffectsreact'
containerRegistry: 'videoeffects.azurecr.io'
dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
tag: '$(Build.BuildId)'
# Agent VM image name
vmImageName: 'ubuntu-18.04'
stages:
- stage: Build
displayName: Build and push stage
jobs:
- job: Build
displayName: Build
pool:
vmImage: $(vmImageName)
steps:
- task: Docker@2
displayName: Build and push an image to container registry
inputs:
command: buildAndPush
repository: $(imageRepository)
dockerfile: $(dockerfilePath)
containerRegistry: $(dockerRegistryServiceConnection)
tags: |
$(tag)
latest