【问题标题】:ReactJs : Call method from another component having no relation (parent-child)ReactJs:从另一个没有关系的组件(父子)调用方法
【发布时间】:2022-01-24 08:09:19
【问题描述】:

我有一个组件 ->

AppLanding 渲染 2 个其他组件的组件 -

AppActions
AppListings

AppActions 和 AooListings 之间没有联系。

点击AppAction中的按钮,我想调用AppListings中的方法。

这样做的必要性-

AppListings 包含 Ag-GridAppActions 包含按钮操作。点击AppActions 中的按钮,我想调用AppListings 中的方法,该方法控制AppListings 中Ag-Grid 的columnapi

如果它有父子关系,我会将方法传递给AppListings,但在这种情况下我不能,因为它没有关系。

【问题讨论】:

    标签: javascript jquery reactjs


    【解决方案1】:

    您希望同级组件进行通信。你可能想看看这个答案:https://stackoverflow.com/a/36144048/1065780

    这个想法是要么使用像redux 这样的状态管理器,要么让你的父组件接收来自一个兄弟姐妹的事件并将更改的道具传递给另一个兄弟姐妹,如下所示:

    function AppLanding() {
      const [isSomethingToggled, setIsSomethingToggled] = React.useState(false);
    
      const handleAction = () => {
        setIsSomethingToggled(!isSomethingToggled);
      };
      
      return (
        <div>
          <AppActions onClick={handleAction} />
          <AppListings isSomethingToggled={isSomethingToggled} />
        </div>
      );
    }
    
    function AppActions({ onClick }) {
      return (
        <div>
          <button onClick={onClick}>Click action</button>
        </div>
      );
    }
    
    function AppListings({ isSomethingToggled }) {
      return <div>Is something toggled: {isSomethingToggled ? 'yes' : 'no'}</div>;
    }
    
    ReactDOM.render(<AppLanding />, document.getElementById('root'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
    
    
    <div id="root">
    </div>

    【讨论】:

      【解决方案2】:

      您可以在AppActions页面中按钮的点击事件上使用redux,并在AppListings页面中使用useeffect监听redux状态。

      const AppActions = (props) =>{
          const clickEvent = () => {
              //you can add page restriction
              props.setReduxState({callMethod:true/*, page:"AppActions"*/})
          }
      
          return <button onClick={clickEvent}>Button</button>
      }
      
      const mapDispatchToProps = {
          setReduxState: reduxStateOperations.setReduxState
      }
      
      const connector = Redux.connect(null, mapDispatchToProps);
      export default connector(AppActions);
      
      const AppListings = (props) =>{
          const method = () => { console.log("called") }
      
          useEffect(() => {
              if(props.reduxState?.callMethod) {
                  method()
                  props.setReduxState(undefined)
              }
          }, [props.reduxState])
      
          return <>AppListings Page</>
      }
      
      const mapStateToProps = (state: any) => {
          return {
              reduxState: state.reduxState.reduxState,
          }
      }
      const mapDispatchToProps = {
          setReduxState: reduxStateOperations.setReduxState
      }
      
      const connector = Redux.connect(mapStateToProps, mapDispatchToProps);
      export default connector(AppListings);
      

      【讨论】:

        【解决方案3】:

        您是否考虑过使用 React.Context 创建全局提供程序(或专门针对您的布局)?这样你就可以将你的动作存储在一个 reducer 中。

        钩子/use-context.jsx

        import React from 'react'
        
        // Set a relevant initial state
        const INITIAL_STATE = {}
        
        // Add actions for your application
        const ACTIONS = {
          UPDATE_VAR: 'update-var',
          DELETE_VAR: 'delete-var'
        }
        
        const reducer = (state, action) => {
          const next = { ...state } // Shallow copy
        
          switch (action.type) {
            case ACTIONS.UPDATE_VAR:
              next.var = action.data
              break
            case ACTIONS.DELETE_VAR:
              delete next.var
              break
          }
        
          return next
        }
        
        const Context = React.createContext({
          state: { ...INITIAL_STATE },
          dispatch: () => null
        })
        
        export const Provider = ({ children }) => {
          const [state, dispatch] = React.useReducer(
            reducer, init(false)
          )
        
          return (
            <Context.Provider value={[state, dispatch, ACTION]}>
              {children}
            </Context.Provider>
          )
        }
        
        // Rename to something relevant
        const useContext = () => {
          const [state, dispatch] = React.useContext(Context)
        
          return [state, dispatch]
        }
        
        export default useContext
        

        pages/index.jsx:提供状态

        import { Provider } from '../hooks/use-context'
        
        const Page = () => (
          <Provider>
            <AppActions />
            <AppListings />
          </Provider>
        )
        
        export default Page
        

        components/app-actions.jsx:更新状态

        import useContext from '../hooks/use-context'
        
        const AppActions = () => {
          const [, dispatch] = useContext()
        
          return (
            <button onClick={() => dispatch(/* action */)>
              Click Me
            </button>
          )
        }
        
        export default AppActions
        

        components/app-listings.jsx:消费状态

        import useContext from '../hooks/use-context'
        
        const AppListings = () => {
          const [state] = useContext()
        
          return (
            <pre>{JSON.stringify(state, null, 2)</pre>
          )
        }
        
        export default AppListings 
        

        您还可以查看第三方解决方案,例如 Redux

        【讨论】:

          猜你喜欢
          • 2017-08-19
          • 2017-11-24
          • 1970-01-01
          • 2021-06-10
          • 1970-01-01
          • 2017-10-26
          • 2020-10-14
          • 2019-11-11
          相关资源
          最近更新 更多