Javascript 主组件仅在刷新时加载(不在初始加载时),竞态条件?
我遇到的情况是,当第一次加载页面时,应该加载在Javascript 主组件仅在刷新时加载(不在初始加载时),竞态条件?,javascript,html,css,reactjs,Javascript,Html,Css,Reactjs,我遇到的情况是,当第一次加载页面时,应该加载在Home.js中的图像不会加载,直到在浏览器(Chrome)上按下刷新按钮。这种情况发生在开发服务器和实时生产服务器中,有时必须在图像显示之前多次点击刷新 请注意,我对所有web开发都是新手,而且我的大部分经验都是在Android开发中 我认为这与我将图像加载到主组件的方式有关。通过日志记录,我发现图像是在页面加载之前加载的(使用componentDidMount()),因此我正在寻找任何可用的解决方案 谢谢,这是密码 Main.js: import
Home.js
中的图像不会加载,直到在浏览器(Chrome)上按下刷新按钮。这种情况发生在开发服务器和实时生产服务器中,有时必须在图像显示之前多次点击刷新
请注意,我对所有web开发都是新手,而且我的大部分经验都是在Android开发中
我认为这与我将图像加载到主组件的方式有关。通过日志记录,我发现图像是在页面加载之前加载的(使用componentDidMount()
),因此我正在寻找任何可用的解决方案
谢谢,这是密码
Main.js:
import React from 'react';
import { withRouter, Route, NavLink, HashRouter } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faInstagram, faGithub, faFacebook } from '@fortawesome/fontawesome-free-brands';
import 'bootstrap/dist/css/bootstrap.css';
import Favicon from 'react-favicon';
import Home from './Home';
import Contact from './Contact';
import socialMediaLinks from './utilities/Utils';
class Main extends React.Component {
constructor() {
super();
this.state = {
screenWidth: null,
isMobile: false,
};
this.handleResize = this.handleResize.bind(this);
}
componentDidMount() {
window.addEventListener('resize', this.handleResize.bind(this));
this.handleResize();
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
}
handleResize() {
this.setState({ screenWidth: window.innerWidth });
console.log(`width is ${this.state.screenWidth}`);
}
render() {
return (
<HashRouter>
<div>
<Favicon url='./favicon.ico' />
{/* Navigation */}
<nav className='navbar fixed-top bg-dark flex-md-nowrap'>
{/* Social Media */}
<a className='social-media-link' href={socialMediaLinks['instagram']}><FontAwesomeIcon icon={faInstagram} size='lg' /></a>
<a className='social-media-link' href={socialMediaLinks['github']}><FontAwesomeIcon icon={faGithub} size='lg' /></a>
<a className='social-media-link' href={socialMediaLinks['facebook']}><FontAwesomeIcon icon={faFacebook} size='lg' /></a>
<ul className="header">
<li className='nav-option'><NavLink exact to='/'>Home</NavLink></li>
<li className='nav-option'><NavLink to='/contact'>About/Contact</NavLink></li>
</ul>
</nav>
{/* Main Page */}
<div className='content container-fluid' align='center'>
<div className='row'>
<Route exact path='/' component={withRouter(Home)} />
<Route path='/contact' component={withRouter(Contact)} />
</div>
<footer>Created by me :)</footer>
</div>
</div>
</HashRouter>
);
}
}
export default Main;
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
<link rel='icon' href='../src/favicon.ico' type='image/x-icon' />
</head>
<body>
<div id="root"></div>
</body>
</html>
这导致:
硬重新加载后(ctrl+F5):
images=[undefined,undefined,undefined,undefined,undefined,undefined,undefined]
刷新后(ctrl+R):
images=[{…},{…},{…},{…},{…},{…},{…},{…}]
--所有这些都带有typeof:Symbol(react.element),键入:“img”
控制台。log
不能保证是同步的,所以执行顺序不能依赖于它。有些引擎是,有些不是
我也不会依赖于require.context
,尤其是当您使用createreact应用程序时。见:
一般来说,如果您的项目已经为ES模块设置好,并且您发现自己需要require
,那么在我看来,这有点像代码味道。ES模块的整个要点是使作用域成为静态的,而不是动态的,这样编译器就可以推断缩小时要丢弃什么。目录结构在运行时实际上不再存在;它全部被缩小成一个大文件,要么由WebpackDev服务器动态运行,要么作为产品构建的一部分
文件是否太多,无法直接导入模块?您可以为imageList
设置一个单独的模块来处理加载和导出,然后只需import
并直接在组件中使用即可:
然后,您可以进行一个测试,以确保将来不会遗漏任何测试(注意,测试直接使用文件结构在节点中运行,而不是Web包最终过程):
如果确实有太多的代码,或者它们会经常更改,我通常喜欢在命令行上自动创建代码。下面是quick n dirty,但应接近您所需的,具体取决于路径:
#!/usr/bin/env node
const { readdirSync, writeFileSync } = require('fs')
const { extname, join } = require('path')
const relPath = (...paths) => join(__dirname, ...paths)
const dir = relPath('src', 'images')
const printLoaderFile = () => {
const imageFiles = readdirSync(dir).filter((file) => {
return extname(file).match(/\.(png|jpe?g|svg)$/)
})
const output = []
imageFiles.forEach((file, index) => {
output.push(`import image${index} from '${dir}/${file}'`)
})
output.push('\nexport default {')
imageFiles.forEach((file, index) => {
output.push(` '${file}': image${index},`)
})
output.push('}\n')
writeFileSync(relPath('src', 'imagesList.js'), output.join('\n'))
}
printLoaderFile()
console.log
不能保证是同步的,所以执行顺序不能依赖于它。有些引擎是,有些不是
我也不会依赖于require.context
,尤其是当您使用createreact应用程序时。见:
一般来说,如果您的项目已经为ES模块设置好,并且您发现自己需要require
,那么在我看来,这有点像代码味道。ES模块的整个要点是使作用域成为静态的,而不是动态的,这样编译器就可以推断缩小时要丢弃什么。目录结构在运行时实际上不再存在;它全部被缩小成一个大文件,要么由WebpackDev服务器动态运行,要么作为产品构建的一部分
文件是否太多,无法直接导入模块?您可以为imageList
设置一个单独的模块来处理加载和导出,然后只需import
并直接在组件中使用即可:
然后,您可以进行一个测试,以确保将来不会遗漏任何测试(注意,测试直接使用文件结构在节点中运行,而不是Web包最终过程):
如果确实有太多的代码,或者它们会经常更改,我通常喜欢在命令行上自动创建代码。下面是quick n dirty,但应接近您所需的,具体取决于路径:
#!/usr/bin/env node
const { readdirSync, writeFileSync } = require('fs')
const { extname, join } = require('path')
const relPath = (...paths) => join(__dirname, ...paths)
const dir = relPath('src', 'images')
const printLoaderFile = () => {
const imageFiles = readdirSync(dir).filter((file) => {
return extname(file).match(/\.(png|jpe?g|svg)$/)
})
const output = []
imageFiles.forEach((file, index) => {
output.push(`import image${index} from '${dir}/${file}'`)
})
output.push('\nexport default {')
imageFiles.forEach((file, index) => {
output.push(` '${file}': image${index},`)
})
output.push('}\n')
writeFileSync(relPath('src', 'imagesList.js'), output.join('\n'))
}
printLoaderFile()
通过以下方式修改Home.js
,可以快速加载图像,而无需刷新:
import React from 'react';
import 'bootstrap/dist/css/bootstrap.css';
import './index.css';
var imageList = [];
function importAll(r) {
const keys = r.keys();
let images = {};
for (var k in keys) {
images[keys[k].replace('./', '')] = r(keys[k]);
}
return images;
}
const images = importAll(require.context('./images/resized/', false, /\.(png|jpe?g|svg)$/));
for (var image in images) {
var newImage = new Image(images[image], images[image], null);
newImage.name = images[image];
newImage.src = images[image];
imageList.push(newImage);
}
class Home extends React.Component {
constructor() {
super();
this.state = {
images: [],
}
}
componentDidMount() {
this.setState({ images: imageList });
}
render() {
let imagesFinal = [];
for (var image in this.state.images) {
console.log(this.state.images[image].src);
if (this.state.images[image].naturalHeight > this.state.images[image].naturalWidth) {}
imagesFinal.push(<img src={this.state.images[image].src} className='landscape-img' alt=''></img>);
}
return <div>{imagesFinal}</div>;
}
}
export default Home;
从“React”导入React;
导入'bootstrap/dist/css/bootstrap.css';
导入“./index.css”;
var imageList=[];
函数输入(r){
常量键=r.键();
让图像={};
for(键中的变量k){
图像[keys[k]。替换('./','')=r(keys[k]);
}
返回图像;
}
const images=importAll(require.context(“./images/resized/”,false,/\(png | jpe?g | svg)$/);
用于(图像中的var图像){
var newImage=新图像(图像[Image],图像[Image],空);
newImage.name=图像[图像];
newImage.src=images[image];
imageList.push(newImage);
}
类Home扩展了React.Component{
构造函数(){
超级();
此.state={
图像:[],
}
}
componentDidMount(){
this.setState({images:imageList});
}
render(){
设imagesFinal=[];
for(此.state.images中的var图像){
console.log(this.state.images[image].src);
如果(this.state.images[image].naturalHeight>this.state.images[image].naturalWidth){}
imagesFinal.push();
}
返回{imagesFinal};
}
}
导出默认主页;
通过以下方式修改Home.js
,导致图像加载速度快且无需刷新:
import React from 'react';
import 'bootstrap/dist/css/bootstrap.css';
import './index.css';
var imageList = [];
function importAll(r) {
const keys = r.keys();
let images = {};
for (var k in keys) {
images[keys[k].replace('./', '')] = r(keys[k]);
}
return images;
}
const images = importAll(require.context('./images/resized/', false, /\.(png|jpe?g|svg)$/));
for (var image in images) {
var newImage = new Image(images[image], images[image], null);
newImage.name = images[image];
newImage.src = images[image];
imageList.push(newImage);
}
class Home extends React.Component {
constructor() {
super();
this.state = {
images: [],
}
}
componentDidMount() {
this.setState({ images: imageList });
}
render() {
let imagesFinal = [];
for (var image in this.state.images) {
console.log(this.state.images[image].src);
if (this.state.images[image].naturalHeight > this.state.images[image].naturalWidth) {}
imagesFinal.push(<img src={this.state.images[image].src} className='landscape-img' alt=''></img>);
}
return <div>{imagesFinal}</div>;
}
}
export default Home;
从“React”导入React;
导入'bootstrap/dist/css/bootstrap.css';
导入“./index.css”;
var imageList=[];
函数输入(r){
常量键=r.键();
让图像={};
for(键中的变量k){
图像[keys[k]。替换('./','')=r(keys[k]);
}
返回图像;
}
const images=importAll(require.context(“./images/resized/”,false,/\(png | jpe?g | svg)$/);
用于(图像中的var图像){
var newImage=新图像(图像[Image],图像[Image],空);
newImage.name=图像[图像];
newImage.src=images[image];
imageList.push(newImage);
}
类Home.C
// imageList.js
import foo from './images/foo.jpg'
import bar from './images/bar.jpg'
import baz from './images/baz.jpg'
import blah from './images/blah.jpg'
export default {
foo,
bar,
baz,
blah,
}
// __tests__/imagesList.test.js
import imageList from '../imageList'
import fs from 'fs'
import path from 'path'
const dir = path.join(__dirname, '..', 'images')
it('has all the images', () => {
const imageFiles = fs.readdirSync(dir).filter((file) => {
return path.extname(file).match(/\.(png|jpe?g|svg)$/)
})
expect(Object.keys(imageList)).toEqual(imageFiles)
})
#!/usr/bin/env node
const { readdirSync, writeFileSync } = require('fs')
const { extname, join } = require('path')
const relPath = (...paths) => join(__dirname, ...paths)
const dir = relPath('src', 'images')
const printLoaderFile = () => {
const imageFiles = readdirSync(dir).filter((file) => {
return extname(file).match(/\.(png|jpe?g|svg)$/)
})
const output = []
imageFiles.forEach((file, index) => {
output.push(`import image${index} from '${dir}/${file}'`)
})
output.push('\nexport default {')
imageFiles.forEach((file, index) => {
output.push(` '${file}': image${index},`)
})
output.push('}\n')
writeFileSync(relPath('src', 'imagesList.js'), output.join('\n'))
}
printLoaderFile()
import React from 'react';
import 'bootstrap/dist/css/bootstrap.css';
import './index.css';
var imageList = [];
function importAll(r) {
const keys = r.keys();
let images = {};
for (var k in keys) {
images[keys[k].replace('./', '')] = r(keys[k]);
}
return images;
}
const images = importAll(require.context('./images/resized/', false, /\.(png|jpe?g|svg)$/));
for (var image in images) {
var newImage = new Image(images[image], images[image], null);
newImage.name = images[image];
newImage.src = images[image];
imageList.push(newImage);
}
class Home extends React.Component {
constructor() {
super();
this.state = {
images: [],
}
}
componentDidMount() {
this.setState({ images: imageList });
}
render() {
let imagesFinal = [];
for (var image in this.state.images) {
console.log(this.state.images[image].src);
if (this.state.images[image].naturalHeight > this.state.images[image].naturalWidth) {}
imagesFinal.push(<img src={this.state.images[image].src} className='landscape-img' alt=''></img>);
}
return <div>{imagesFinal}</div>;
}
}
export default Home;