我有一个应用程序,从GraphQL数据库中提取数据,然后将其映射到自定义表单组件(数量数字文本框).现在,组件本身保存着它们各自数量的状态,但我需要能够从父级访问这些值,以便我可以使用应用程序中其他地方的输入来更改数量.我已经查看了这是如何完成的,我认为这可能是我需要的,但我不知道如何应用它:[How to Target DOM with reaction useRef in map][1]
我的应用程序由一个父元素、一个包含输入的Top Bar、一个modal组件和一个从GraphQL查询填充的元素映射组成.
export default function Home() {
const [batch, setBatch] = useState([]);
const [target, setTarget] = useState("");
const [batchCount, setBatchCount] = useState(0);
const [cartModalStatus, setCartModalStatus] = useState(false);
const elementValues = useRef([]);
const fetcher = query => request("https://data.objkt.com/v2/graphql", query);
const { data, error } = useSWR(
`{
listing(where: {token: {creators: {creator_address: {_eq: ` + target + `}}, supply: {_gt: "0"}}, status: {_eq: "active"}}, order_by: {token: {timestamp: asc}, price: asc}) {
token {
name
display_uri
timestamp
supply
}
price
seller {
address
alias
}
amount_left
}
}`, fetcher);
const handleItemCount = () => {
let count = 0;
for (let i = 0; i < batch.length; i++)
count += batch[i][1];
setBatchCount(count);
}
const onCartClick = () => {
setCartModalStatus(true);
}
const onHideModal = () => {
setCartModalStatus(false);
}
const onSubmit = (e) => {
console.log(e);
setTarget(e.target[0].value);
e.preventDefault();
};
const onChange = (el, quantity) => {
let batchCopy = batch;
let found = false;
let foundIndex;
for (var i = 0; i < batchCopy.length; i++)
if (batchCopy[i][0] === el)
{
found = true;
foundIndex = i;
}
if (!found) batchCopy.push([el, quantity]);
else if (found) batchCopy[foundIndex][1] = quantity
setBatch(batchCopy);
handleItemCount();
};
return (
<Container>
<TopBar onSubmit={onSubmit} cartTotal={batchCount} onCartClick={onCartClick}/>
<CartModal show={cartModalStatus} onHideModal={onHideModal} batch={batch}/>
<DataMap target={target} onChange={onChange} data={data} error={error}/>
</Container>
)
}
DataMap是来自查询的数据.我需要将每个元素与一个数量相匹配,这是通过在每个子元素中保留单独的状态来实现的,但我需要父元素能够访问该数量.
export function DataMap(props){
const onChange = (el, quantity) => {
console.dir(el);
props.onChange(el, quantity);
};
if (props.target === "") return <div>No target.</div>;
if (props.target !== "" && validateAddress(props.target) !== 3) return <div>Invalid address.</div>;
if (props.error) {
console.log(props.error);
return <div>Failed to Load</div>;
}
if (!props.data) return <div>Loading...</div>;
if (!props.error && props.data){
return <Row>
{props.data["listing"]
.map((el, i , arr) => {
return (
<Col key={i} id={i} xs={4} sm={4} md={3} lg={2}>
<StateImg src={"https://ipfs.io/ipfs/" + el["token"]["display_uri"].slice(7,)}/>
<h5>{el["token"]["name"]}</h5>
<p>{el["price"] / 1000000} {" xtz"}</p>
<Row>
<QuantityForm remaining={el["amount_left"]} onChange={onChange} element={el}/>
</Row>
</Col>)
})}
</Row>
}
}
最后,QuantityForms只是每件商品数量的表单输入.现在,状态保存在每个单独的元素中,并向上传递到父元素的"批处理"状态,但这意味着除了使用这些特定的输入之外,我不能改变数量.
export function QuantityForm(props){
const [quantity, setQuantity] = useState(0);
useEffect(()=>{
props.onChange(props.element, quantity);
}, [props.element, quantity]);
const onChange = (e) => {
setQuantity(parseInt(e.target.value));
e.preventDefault();
};
return (
<Form.Group>
<Form.Label>Quantity</Form.Label>
<InputGroup>
<Form.Control onChange={onChange} onKeyDown={(e)=>{e.preventDefault();}} type={"number"} value={quantity} min={0} max={props.remaining} aria-describedby="basic-addon1"/>
<InputGroup.Text id="basic-addon1">
{"/" + props.remaining}
</InputGroup.Text>
</InputGroup>
</Form.Group>
);
}
我们非常感谢在使用ref访问映射的QuantityForms值方面的任何帮助. [1]:How target DOM with react useRef in map