我正在遍历基于多个数组创建的几个组件。当我单击delete
时,这会减少数组,从而减少组件数量。
import React, { useState } from "react";
const FooList = props => {
const [number, setNumber] = useState("");
const deleteArray = () => {
// Remove the component that was clicked
props.setArray(prev => prev.filter(a => a !== props.current));
};
return (
<>
<input
type="number"
placeholder="Phone"
onChange={e => setNumber(e.target.value)}
value={number}
/>
<button onClick={() => deleteArray()}>delete</button>
</>
);
};
export default FooList;
import React, { useState } from "react";
import FooList from "./FooList";
const Foos = props => {
const [array, setArray] = useState([]);
const addToarray = (id: number) => {
const obj = { id };
const a: any = array.concat(obj);
console.log(a);
setArray(a);
};
return (
<>
{array.map((a, index) => (
<div key={index}>
<FooList current={a} setArray={setArray} />
</div>
))}
<button onClick={() => addToarray(Math.random())}>add</button>
</>
);
};
export default Foos;
<Foos />
[我希望输入一个大于一个的值,并且当我按delete
时,该组件应与输入的值一起删除。
如果列表组件中有项目,并且项目必须从列表中接收功能以更改或删除项目,则最好optimize这些功能以防止重新渲染。
这是优化的列表和项目的示例:
FooItem:
import React, { memo, useMemo } from "react";
//make this a pure component using React.memo
const FooItemContainer = memo(props => {
const {
remove,
change,
current: { id, val }
} = props;
//only logs for item(s) that actually change
console.log("in item container for id:", id);
//add events to props
const propsWithActions = useMemo(
() => ({
change: e => change(id, e.target.value),
remove: () => remove(id),
val
}),
[change, remove, val, id]
);
return useMemo(() => FoodList(propsWithActions), [propsWithActions]);
});
const FoodList = ({ change, remove, val }) =>
console.log("in item presentation", val) || (
<>
<input type="number" placeholder="Phone" onChange={change} value={val} />
<button onClick={remove}>delete</button>
</>
);
export default FooItemContainer;
FooList:
import React, { useState, useEffect, useCallback } from "react";
import FooItem from "./FooItem";
//function to create unique id
const crateId = (num => () => num++)(1);
//do not re reference item callback functions
// detailed explanation can be found here:
// https://stackoverflow.com/a/58192552/1641941
function useEventCallback(fn) {
//ref will never change during component life cycle
const ref = React.useRef();
//every time useEventCallback is called we set ref.current again.
// we can add fn as a dependency but if you see how Parent calls it
// it will have the same outcome because useEventCallback(()=>...)
// causes fn to be different every time anyway
useEffect(() => {
ref.current = fn;
});
//here we return a function that will never change during the component
// life cycle but what it does will change during it's life cycle
// because we keep mutating ref and resetting ref.current
return useCallback(
(...args) => ref.current.apply(void 0, args),
[] //you can do [ref] here but linter knows ref will never change so no needfor it
);
}
const Foos = props => {
const [array, setArray] = useState([]);
const addToarray = useEventCallback(() => {
setArray(array.concat({ id: crateId(), val: "" }));
});
const remove = useEventCallback(id =>
setArray(array.filter(item => id !== item.id))
);
const change = useEventCallback((id, val) =>
setArray(array.map(item => (id !== item.id ? item : { ...item, val })))
);
return (
<>
<button onClick={addToarray}>add</button>
{array.map(a => (
<div key={a.id}>
<FooItem current={a} remove={remove} change={change} />
</div>
))}
</>
);
};
export default Foos;