我应该将功能保持在本地状态

时间:2018-08-10 18:25:17

标签: javascript reactjs

以前从来没有真正做过这样的事情,也找不到很多有关它的信息,但是将函数引用存储在组件的本地状态是否不好?

class Foo extends React.Component{
    this.state = {
      exampleFunction: () => {}
    }
}

它将被传递到另一个组件中,该组件可以更改此功能的功能。

// bar.js component

handleChange = (newFunction) => {
  const { exampleFunction } = this.props;
  this.setState({ exampleFunction: newFunction });
}

如果这不好,应该怎么做?这不是redux存储,只是对本地状态做出反应。

2 个答案:

答案 0 :(得分:1)

我只是在考虑您正在尝试什么,我认为它实际上并没有按照您的想法进行。当您将该函数传递给子组件时,调用this.setState并不是在设置父组件的状态,而是在更改子组件的状态。因此,您实际上并没有更改功能。而且,道具是只读的,因此我认为您不能重新分配它们。

class Parent extends Component {
  state = { visible: true };

  render() {
    const { visible } = this.state;
    return <Child visible={visible} />;
  }
}

class Child extends Component {
  // props.visible = true
  onChange = () => {
    this.setState({ visible: false });
    // props.visible is still true here, child has it's own state
  }
}

上面的代码演示了这一点,当在子级中调用onChange时,来自父级的props.visible仍然为true,因为子级组件具有自己的状态。因此,您的功能也会发生同样的事情。不过,有一种方法可以执行此操作,请查看下面的代码:

class Parent extends Component {
  dynamicFunction = () => {};

  setDynamicFunction(newFunc) {
    this.dynamicFunction = newFunc;
  }

  render() {
    return <Child setDynamicFunction={this.setDynamicFunction} />;
  }
}

class Child extends Component {
  onSomeEvent = () => {
    this.props.setDynamicFunction(newFunction);
  }
}

如果您只想更新父级的动态功能并仅在父级中使用它,则可以执行我上面的操作,但是如果您希望孩子知道动态功能何时更改,您将需要将动态函数从类移到状态,这样,当您更改动态函数时,它将导致子级重新渲染,并将获得新设置的动态函数作为道具传递

答案 1 :(得分:1)

如果要将方法传递给深度嵌套的组件,则可能需要研究React Context API。
请参阅文章Updating Context from a Nested Component

仅出于将钻探方法应用于子组件的目的而使用Redux是一个过大的杀伤力。

实际上,React文档将方法传递给子组件。
下面是从提到的文档中复制的代码

使用toggleTheme的空实现创建上下文。

export const ThemeContext = React.createContext({
  theme: themes.dark,
  toggleTheme: () => {},
});

然后,将toggleTheme传递给消费者,该按钮由按钮使用。

import {ThemeContext} from './theme-context';

function ThemeTogglerButton() {
  // The Theme Toggler Button receives not only the theme
  // but also a toggleTheme function from the context
  return (
    <ThemeContext.Consumer>
      {({theme, toggleTheme}) => (
        <button
          onClick={toggleTheme}
          style={{backgroundColor: theme.background}}>
          Toggle Theme
        </button>
      )}
    </ThemeContext.Consumer>
  );
}

提供者(通过toggleTheme实现的提供者)使toggleTheme可供上下文使用者使用。

class App extends React.Component {
  constructor(props) {
    super(props);

    this.toggleTheme = () => { ... };

    // State also contains the updater function so it will
    // be passed down into the context provider
    this.state = {
      theme: themes.light,
      toggleTheme: this.toggleTheme,
    };
  }

  render() {
    // The entire state is passed to the provider
    return (
      <ThemeContext.Provider value={this.state}>
        <Content />
      </ThemeContext.Provider>
    );
  }
}

<ThemeContext.Provider value={this.state}>,您可以在其中提供toggleTheme的实现。