我正在尝试在我制作的两个组件之间共享状态。根据我的研究,我认为我需要将状态提升到一个祖先组件,然后将其细化到其他组件。作为参考,我添加了一个文件上传器,该文件上传器将接收json文件,然后将通过json进行逻辑文件循环,然后将数据呈现到具有新值的表中。
https://reactjs.org/docs/lifting-state-up.html
我对如何在这些组件之间共享状态以及对任何批评表示赞赏。
FileUploader.js
import React, { useCallback, useState } from 'react'
import { useDropzone } from 'react-dropzone'
import RoombaClean from './Roomba'
const style = {
margin: '10% 30% 10% 30%',
flex: 1,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
padding: '30px',
borderWidth: 1,
borderRadius: '20px',
borderColor: '#bdbdbd',
borderStyle: 'dashed',
backgroundColor: '#eeeeee',
color: '#bdbdbd',
outline: 'none',
transition: 'border .24s ease-in-out',
};
function FileUploader() {
const [state, setState] = useState("");
const onDrop = useCallback((acceptedFiles) => {
acceptedFiles.forEach((file) => {
const reader = new FileReader()
reader.onabort = () => console.log('file reading was aborted')
reader.onerror = () => console.log('file reading has failed')
reader.onload = () => {
const inputJson =
JSON.parse(reader.result)
console.log(inputJson)
setState(inputJson);
//apply logic to transform json
}
reader.readAsText(file)
})
}, [])
const {getRootProps, getInputProps} = useDropzone({onDrop})
return (
<div {...getRootProps({style})}>
<input {...getInputProps()} value={state}/>
<p>Drag files here, or click to browse</p>
</div>
)
}
export default FileUploader;
Ancestor.js
import React, { useState } from 'react'
import FileUploader from './FileUploader'
import Table from './Table'
function Ancestor() {
const [state, setState] = useState('');
return <>
<FileUploader state={state} />
<Table state={state} />
</>;
}
export default Ancestor;
Table.js
import React from 'react'
function Table() {
return (
<div>
<table className="table">
<thead>
<tr>
<th>Step</th>
<th>Roomba Location</th>
<th>Action</th>
<th>Total Dirt Collected</th>
<th>Total Wall Hits</th>
</tr>
</thead>
<tbody>
{
}
</tbody>
</table>
<h4>Final Position: {}</h4>
<h4>Total Dirt Collected: {}</h4>
<h4>Total Distance Traveled: {}</h4>
<h4>Total Walls Hit: {}</h4>
</div>
)
}
export default Table
答案 0 :(得分:1)
import React, { useState } from 'react'
import FileUploader from './FileUploader'
import Table from './Table'
const Ancestor = () => {
const [products, setProducts] = useState({});
return <>
<FileUploader productState={products} setProductState={setProducts} />
<Table productState={products} />
</>;
}
export default Ancestor;
function FileUploader({ productState, setProductState }) {
const onDrop = useCallback((acceptedFiles) => {
acceptedFiles.forEach((file) => {
const reader = new FileReader()
reader.onload = () => {
const inputJson =
JSON.parse(reader.result)
setProductState(inputJson); // Here's where the magic happens
}
reader.readAsText(file)
})
}, [])
const {getRootProps, getInputProps} = useDropzone({onDrop})
return (
<div {...getRootProps({style})}>
<input {...getInputProps()} value={productState}/>
<p>Drag files here, or click to browse</p>
</div>
)
}
function Table({ productState }) {
return (
<div>
<table className="table">
<thead>
<tr>
<th>Step</th>
<th>Roomba Location</th>
<th>Action</th>
<th>Total Dirt Collected</th>
<th>Total Wall Hits</th>
</tr>
</thead>
<tbody>
{/* Use the productState here */}
</tbody>
</table>
<h4>Final Position: {}</h4>
<h4>Total Dirt Collected: {}</h4>
<h4>Total Distance Traveled: {}</h4>
<h4>Total Walls Hit: {}</h4>
</div>
)
}
用道具“ productState”和“ setProductState”替换子状态(FileUpload.js和Table.js)中的状态和setState。
在父组件(Ancestor.js)中声明useState
通过步骤1中声明的道具,将父组件(产品,setProducts)中声明的状态和setState传递给子级。
使用FileUpload.js中传递的setState更改状态。
更改会在父级和子级之间传播。
注意:您可以使用useContext钩子实现相同的功能,这将使您可以独立于父子关系在整个应用中重用状态。
注意:您还可以使用Redux之类的状态管理库来创建一个集中式存储,其中存储了所有不同的状态,可在整个应用程序中使用。中大型应用程序的首选解决方案。