使用祖先反应提升状态

时间:2020-10-26 16:32:35

标签: reactjs setstate

我正在尝试在我制作的两个组件之间共享状态。根据我的研究,我认为我需要将状态提升到一个祖先组件,然后将其细化到其他组件。作为参考,我添加了一个文件上传器,该文件上传器将接收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

1 个答案:

答案 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>
  )
}
  1. 用道具“ productState”和“ setProductState”替换子状态(FileUpload.js和Table.js)中的状态和setState。

  2. 在父组件(Ancestor.js)中声明useState

  3. 通过步骤1中声明的道具,将父组件(产品,setProducts)中声明的状态和setState传递给子级。

  4. 使用FileUpload.js中传递的setState更改状态。

  5. 更改会在父级和子级之间传播。

注意:您可以使用useContext钩子实现相同的功能,这将使您可以独立于父子关系在整个应用中重用状态。

注意:您还可以使用Redux之类的状态管理库来创建一个集中式存储,其中存储了所有不同的状态,可在整个应用程序中使用。中大型应用程序的首选解决方案。