问题描述
我正在尝试重构我现有的代码以使用 Hooks 而不是构造函数、componentDidMount()、componentDidUpdate()。我下面的原始代码做得很好:
import React from "react";
import '../css/App.css';
import 'jquery/dist/jquery.js';
import Isotope from 'isotope-layout/dist/isotope.pkgd.min.js';
import projectsData from '../data/projectsData';
import Project from './Projects';
class App extends React.Component {
constructor(props){
super(props);
this.state = {
isotope: null,projectComponents: projectsData.map(project => <Project id={project.id} project={project}/>),}
}
componentDidMount() {
//load isotope masonry view
const elem = document.querySelector('#visContainer')
if (!this.state.isotope) {
this.setState({
isotope: new Isotope( elem,{
//options
itemSelector: '.gridItem',layoutMode: 'masonry',masonry: {
columnWidth: 140,fitWidth: true
},getSortData: {
year: '.yearsstart parseFloat',kind: '.kind'
}
})
});
}
else {
this.state.isotope.reloadItems();
}
}
}
componentDidUpdate() {
if (this.state.isotope) {
this.state.isotope.reloadItems();
this.state.isotope.layout();
}
}
render(){
return (
<body>
<div id='sepLine'>
<div id="visHolder">
<div id="visContainer" style={{position: "relative",width: "840px",height: "1823px"}}>
{this.state.projectComponents}
</div>
</div>
</div>
</body>
);
}
}
export default App
但是,我试图修改它以使用 d3 库而不是映射外部组件(项目)。 并使用 React Hooks 执行此操作。 我在下面使用 d3 映射数据,但我无法将 Isotope 应用于 ID“visContainer”。 我怀疑这是因为它们同时发生,因为它们都在使用 useEffect()?:
import React,{ useEffect,useState } from "react";
import '../css/App.css';
import 'jquery/dist/jquery.js';
import Isotope from 'isotope-layout/dist/isotope.pkgd.min.js';
import projectsData from '../data/projectsData';
import Project from './Projects';
function App () {
const [isotope,setIsotope] = useState(null);
useEffect(() => {
const projects = d3.select('#visContainer');
projects
.selectAll('.lineDiv')
.data(projectsData)
.enter()
.append('div')
.attr('id',(d,i) => {
return d.title })
.attr('className',d => {
return 'lineDiv gridItem y' + d.start.substring(0,4) + ' ' + d.kind + ' ' + d.title + ' ' + d.subtitle.replace(/,/g,' ');
})
},[]);
useEffect(() => {
const elem = document.querySelector('#visContainer')
setIsotope(new Isotope( elem,{
itemSelector: '.gridItem',kind: '.kind'
}
})
)
},[]);
return (
<body>
<div id='sepLine'>
<div id="visHolder">
<div id="visContainer" style={{position: "relative",height: "1823px"}}>
</div>
</div>
</div>
</body>
);
}
export default App
非常感谢任何帮助,因为我很想知道我可以将 React Hooks 推多远。提前致谢!
解决方法
我通过在初始加载到 setProjects() 和映射时使用“useEffect”来解决这个问题。然后 Isotope 使用
控制“#visContainer”document.querySelector('#visContainer')
const App = (props) => {
const [projects,setProjects] = useState(null);
const [isotope,setIsotope] = useState(null);
useEffect(() => {
setProjects(projectsData.map(project => <Project id={project.id} project={project} onClick={filterThisProject}/>))
},[])
useEffect(() => {
const elem = document.querySelector('#visContainer')
setIsotope(new Isotope( elem,{
itemSelector: '.gridItem',layoutMode: 'masonry',masonry: {
columnWidth: 140,fitWidth: true
},getSortData: {
year: '.start parseFloat',kind: '.kind'
}
})
)
},[projects]);
return (
<body>
<div id='sepLine'>
<div id="visHolder">
<div id="visContainer" style={{position: "relative",width: "840px",height: "1823px"}} >
{projects}
</div>
</div>
</div>
</body>
);
}
export default App;