我正在使用react-hooks管理JSX.Elements列表。但是,一旦更改了元素,尝试删除它会导致意外的行为。
我曾经尝试过使用useReducer,按索引删除等,但是仍然出现了意外的更新结果。
$(function(){
const DATASETS = [
{
TYPE: 'KICKSTARTERS',
NAME: 'Kickstarters',
URL: 'https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/kickstarter-funding-data.json'
},
{
TYPE: 'MOVIES',
NAME: 'Movies',
URL: 'https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/movie-data.json'
},
{
TYPE: 'GAMES',
NAME: 'Games',
URL: 'https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/video-game-sales-data.json'
}
];
//REDUX
const INDEX = 'INDEX';
const INITIAL_STATE = 0;
//action generator
function setIndex(index){
return {
type: INDEX,
index
};
}
//reducer
function indexReducer(state = INITIAL_STATE, action){
switch(action.type){
case INDEX: return action.index;
default: return state;
}
}
const store = Redux.createStore(indexReducer);
//react
class DropDown extends React.Component{
constructor(props){
super(props);
this.handler = this.handler.bind(this);
}
handler(e){
this.props.setIndex(e.target.selectedIndex);
}
render(){
return (
<select
id='dropdown'
onChange={this.handler}>
{DATASETS.map(e=><option>{e.NAME}</option>)}
</select>
)
}
}
class Svg extends React.Component{
constructor(props){
super(props);
this.createMap = this.createMap.bind(this);
}
componentDidMount(){
this.createMap();
}
componentDidUpdate(){
this.createMap();
}
createMap(){
const NODE = this.node
const DATASET = DATASETS[this.props.index];
d3.select(NODE)
.html('')
.append('h4')
.attr('id', 'description')
.attr('class', 'text-center')
.html(`Top ${DATASET.NAME}`)
//svg setup
const SVG_PADDING = 20;
const SVG_WIDTH = 1000;
const SVG_HEIGHT = 1400;
var svg = d3.select(NODE)
.append('svg')
.attr('width', SVG_WIDTH)
.attr('height', SVG_HEIGHT)
.attr('id', 'map');
d3.json(DATASET.URL)
.then(
function(data){
//heirarchy and map
var root = d3.hierarchy(data)
.sum(d=>d.balue)
.sort((a,b)=>b.height-a.height || b.value-a.value);
var nodes = d3.treemap()
.size([SVG_WIDTH, SVG_HEIGHT * 2/3])
.padding(1)(root)
.descendants();
//scale
var categories = [...new Set(root.leaves().map(e => e.data.category))].sort();
var unityScale = d3.scaleLinear()
.domain([0, categories.length]).range([0,1]);
var colorScale = d3.scaleSequential(d3.interpolateRainbow);
var discreteScale = d3.scaleOrdinal(d3.schemeCategory20b);
//map cells
var cell = svg.selectAll('.cell')
.data(root.leaves())
.enter().append('g')
.attr('class', 'cell')
.attr('transform', d=>`translate(${d.x0}, ${d.y0})`);
cell.append('rect')
.attr('class', 'tile')
.attr('data-category', d=>d.data.category)
.attr('data-name', d=>d.data.name)
.attr('data-value', d=> d.data.value)
.attr('x', 0).attr('y', 0)
.attr('width', d=>d.x1-d.x0)
.attr('height', d=>d.y1-d.y0)
.attr('fill', d => colorScale(unityScale(categories.indexOf(d.data.category))))
});
}
render(){
const test = d3.select('#container')
return <div ref={node=>this.node=node}/>
}
}
//ReactRedux
const Provider = ReactRedux.Provider;
const connect = ReactRedux.connect;
function mapDispatchToProps(dispatch){
return {
setIndex: index=>dispatch(setIndex(index))
}
}
function mapStateToProps(state){
return {
index: state
}
}
const DropDownConnection = connect(null, mapDispatchToProps)(DropDown);
const SvgConnection = connect(mapStateToProps, null)(Svg);
class Wrapper extends React.Component {
render(){
return(
<Provider store={store}>
<DropDownConnection/>
<SvgConnection/>
</Provider>
)
}
}
ReactDOM.render(<Wrapper/>, $('#container')[0]);
})
我应该更改我的代码,以便我的删除单击将删除匹配的元素?
答案 0 :(得分:0)
有一种解决方法。对于数组中的每个项目。与其直接存储项目,不如将其存储为{id:yourAssignedNumber,内容:item}。
通过这种方式,您可以控制ID,并仅通过比较ID即可将其删除。这样,它将可以正常工作。
import React, { useState, useRef } from 'react';
import { Button, Row, Col } from 'antd';
import { Files } from '../Components/Files/Files';
import { fileHandler } from '../model/fileHandler';
interface Props {
fileHandlers?: fileHandler[];
}
export const FolderPage: React.FC<Props> = ({ fileHandlers }) => {
const [state, setState] = useState([{ key: -1, content: <Files fileHandlers={fileHandlers} /> }]);
const key = useRef(0);
const newFolderPanel = () =>
setState(prev =>
prev.concat({
key: key.current++,
content: <Files fileHandlers={fileHandlers} />
})
);
const removePanel = (key: number) => setState(prevState => prevState.filter(s => s.key !== key));
return (
<Row>
<Button type="primary" icon="plus" onClick={newFolderPanel} style={{ margin: '.75rem' }}>
New Foldr Panel
</Button>
{state.map(({ key, content }) => (
<Col key={key}>
<div
style={{
background: '#75ff8133',
display: 'grid',
justifyItems: 'end',
padding: '.5rem 1rem'
}}>
<Button onClick={() => removePanel(key)} icon="close" type="danger" shape="circle" />
</div>
{content}
</Col>
))}
</Row>
);
};