【问题标题】:How to pass state from hook to display in App hook in React?如何将状态从钩子传递到 React 的 App 钩子中显示?
【发布时间】:2020-04-20 20:10:57
【问题描述】:

如何将info 的状态(数据)发送到 App 挂钩,以便在 div 中显示属性? setInfo(info) 存储了我想要在 Map 挂钩上显示的数据,当我在 _onClickconsole.log(info) 时,我可以看到所有属性。我被困在如何在 App 中使用和显示它。感谢您的帮助。

应用

const App = () => {

  return (
    <div className="App">
      <div className="inner-left map-container">
        <Map />
      </div>
      <div className="inner-right info-container">
        <Nav />
        <Search />
        <div id="info_side">
          {info} // throws an error undefined
        </div>
      </div>
    </div>
  );
}

export default App;

地图

const Map = () => {
    ...
    const [info, setInfo] = useState(null)

    ...

    const _onClick = event => {
        const { features } = event;
        const info = features && features.find(f => f.layer.id === 'icon');
        setInfo(info); // This is what I would like to use in App
    }

    return (
        <ReactMapGL
            {...viewport}
            onViewportChange={_updateViewport}
            width="100%"
            height="100%"
            mapStyle={mapStyle}
            mapboxApiAccessToken={TOKEN}
            onHover={_onHover}
            onClick={_onClick}>

            <Source id="my-data" type="geojson" data={geojson}>
                <Layer {...icon} />
            </Source>

            <div style={navStyle}>
                <NavigationControl onViewportChange={_updateViewport} />
                ...
            </div>
        </ReactMapGL>
    );
}

export default Map;

【问题讨论】:

  • 这个const Map 是个坏名字。它可能与 ES6 的 Map 冲突。
  • 要回答您的查询,您可以使用回调在组件之间共享数据或使用 Flux、Redux 等状态管理系统来存储全局状态
  • 如何通过回调来做到这一点?如果可能的话,我现在想避开 Redux(谢谢你关于 const Map 的建议,我同意我会更新)
  • 这是一场漫长的艰苦战斗,但我会为您节省一些时间,在 react 中,数据通常以一个方向流动,从父组件到子组件,以 props 的形式。您可以将回调函数 prop 传递给子代以调用(例如在挂载时)以“将数据”传回给父代以使用。

标签: javascript reactjs react-hooks react-state-management react-state


【解决方案1】:

您可以将回调道具传递给孩子。

应用

const App = () => {

  const [info, setInfo] = useState(); // local info state

  const displayInfo = () => {
    // this is where I would hope to return the <div>'s with data such as <div>info.Company</div>
    // access current copy of info
  }

  return (
    <div className="App">
      <div className="inner-left map-container">
        <Map onInfoChange={setInfo} /> // pass info state setter to child
      </div>
      <div className="inner-right info-container">
        <Nav />
        <Search />
        <div id="info_side">
          {displayInfo}
        </div>
      </div>
    </div>
  );
}

export default App;

地图

const Map = ({
  onInfoChange, // passed callback prop
}) => {
    ...
    const [info, setInfo] = useState(null)

    // use an effect hook to call callback whenever info updates
    useEffect(() => {
      onInfoChange(info); // pass info back to parent
    }, [info]);

    const _onClick = event => {
        const { features } = event;
        const info = features && features.find(f => f.layer.id === 'icon');
        setInfo(info); // This is what I would like to use in App
    }

    return (
        <ReactMapGL
            {...viewport}
            onViewportChange={_updateViewport}
            width="100%"
            height="100%"
            mapStyle={mapStyle}
            mapboxApiAccessToken={TOKEN}
            onHover={_onHover}
            onClick={_onClick}>

            <Source id="my-data" type="geojson" data={geojson}>
                <Layer {...icon} />
            </Source>

            <div style={navStyle}>
                <NavigationControl onViewportChange={_updateViewport} />
                ...
            </div>
        </ReactMapGL>
    );
}

export default Map;

此时我应该指出,您现在在两个组件中存储了重复的状态,因此将信息状态和逻辑提升到最近的共同祖先 (App) 并简单地将信息作为道具传递给需要它的组件(地图)。 单一事实来源原则。或者正如其他人指出的那样,切换到一个全局状态管理系统,比如 redux,或者使用 React Context(即 react-redux 在后台使用什么)自行开发。

【讨论】:

  • 感谢 Drew 的详尽解释,非常有帮助。在 App 上时,如何显示 {info}?当我点击 时,它会正确地控制台记录日志,但是如果我在 App 上返回(
    {info.properties}
    ),它会在初始加载时抛出未定义的错误。
  • const [info, setInfo] = useState(); // local info state 可以传递一些初始状态,因此它是在初始渲染中定义的。 const [info, setInfo] = useState({ properties: '' }); // local info state 将解决您提到的特定错误的窍门。
【解决方案2】:

如果多个组件共享状态,则状态应由第一个共同祖先管理并通过属性传递。在您的情况下,App 应该管理状态并将您需要的内容作为道具传递给 Map。 但是我们如何根据子事件更新父状态呢?在父组件上创建事件处理器,通过props作为回调函数传递给子组件。

例如,在您的应用上创建回调函数函数:

const [info, setInfo] = useState({});

const handleEvent = event => {
        // Do whatever you need here
        setInfo(info); 
    }

通过 props 将信息(状态)和回调函数传递给孩子:

<Map info={info} clicked={handleEvent}/> //Do not use handleEvent(), otherwise it will call the function immediately 

在 Map 上,使用 props 并将 clicked 设置为事件监听器:

const Map = ({info, clicked}) => { // destructuring pros.info and props.clicked

  <ReactMapGL
            {...viewport}
            onViewportChange={_updateViewport}
            width="100%"
            height="100%"
            mapStyle={mapStyle}
            mapboxApiAccessToken={TOKEN}
            onHover={_onHover}
            onClick={clicked}>

在此处查看更多信息 https://towardsdatascience.com/passing-data-between-react-components-parent-children-siblings-a64f89e24ecf

【讨论】:

    猜你喜欢
    • 2021-09-29
    • 2020-05-23
    • 1970-01-01
    • 2021-02-05
    • 1970-01-01
    • 2020-06-24
    • 2019-08-06
    • 1970-01-01
    • 2020-04-29
    相关资源
    最近更新 更多