reactjs - 使用 Ancestor 响应提升状态

标签 reactjs setstate

我试图在我制作的两个组件之间共享状态。根据我的研究,我相信我需要将状态提升到祖先组件,然后将该状态向下传递到其他组件。作为引用,我添加了一个文件上传器,它将接收一个 json 文件,然后我将通过 json 进行逻辑文件循环,然后该数据将呈现到具有新值的表中。
https://reactjs.org/docs/lifting-state-up.html
我对如何在这些组件之间共享状态感到困惑,并感谢任何批评。
文件上传器.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;


祖先.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;

表.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

最佳答案

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>
  )
}
  • 用 Prop “productState”和“setProductState”替换子项(FileUpload.js 和 Table.js)中的 state 和 setState。
  • 在父组件 (Ancestor.js) 中声明 useState
  • 通过步骤 1 中声明的 props 将父组件(products、setProducts)中声明的 state 和 setState 传递给子组件。
  • 使用 FileUpload.js 中传递的 setState 来更改状态。
  • 更改在父级和子级之间传播。

  • 注:您可以使用 useContext hook 实现相同的效果,这将使您可以在独立于父子关系的应用程序中重用状态。
    注:您还可以使用 Redux 之类的状态管理库来创建一个集中存储,其中存储所有不同的状态,可以在整个应用程序中使用。大中型应用程序的首选解决方案。

    关于reactjs - 使用 Ancestor 响应提升状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64541241/

    相关文章:

    javascript - 如何在 React 中正确更改多个嵌套对象数组的状态?

    javascript - .map 在更新状态后没有重新渲染

    arrays - 在状态 onChange 时将复选框值推送到数组

    flutter - setState 方法在 flutter 中有时有效,有时无效

    javascript - react 类型错误 : Cannot read property 'map' of undefined on passing props

    reactjs - React-nativeanimate.event 自定义 onScroll 监听器

    javascript - 附加到 reactJs 中的无限滚动

    reactjs - 我可以同时使用 Gatsby 和 NEXT.JS 吗?

    node.js - 将 autoprefixer 脚本添加到react-create-app项目中

    flutter - 在Flutter Bloc监听器中调用setState