admin管理员组

文章数量:1355731

Never really done something like this before and couldn't find much information about it but is it bad to store a function reference in a ponent's local state?

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

It'll get passed down into another ponent where that ponent can change the functionality of this function.

// bar.js ponent

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

If this is bad, what should be done instead? This isn't redux store but just react local state.

Never really done something like this before and couldn't find much information about it but is it bad to store a function reference in a ponent's local state?

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

It'll get passed down into another ponent where that ponent can change the functionality of this function.

// bar.js ponent

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

If this is bad, what should be done instead? This isn't redux store but just react local state.

Share Improve this question asked Aug 10, 2018 at 18:25 christiancn7christiancn7 1752 gold badges3 silver badges10 bronze badges 1
  • Why child ponent is going to change parent ponent function? Shall parent ponent use the changed function? – Bartek Fryzowicz Commented Aug 10, 2018 at 18:37
Add a ment  | 

2 Answers 2

Reset to default 4

If you are passing your method to deeply nested ponents, you might want to look into React Context API.
Refer to article, Updating Context from a Nested Component.

Using Redux just for the sake of drilling methods into subponents is an overkill.

In fact, the React documentation passes a method down to child ponents.
below is the code copied from the documentation mentioned

Create a context with an empty implementation of toggleTheme.

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

Then the consumer is passed toggleTheme, which is used by a button.

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>
  );
}

And the provider (it's the one that passes the implementation of toggleTheme) makes toggleTheme available to context consumers.

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}> that is where you provide the implementation of toggleTheme.

I was just thinking about what you're trying, and I don't think it's actually doing what you think. When you pass down the function to the child, and you call this.setState it's not setting the parent ponent's state, it's changing the child ponent's state. So you're not really changing the function. Also, props are read-only, so I don't think you can reassign them.

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
  }
}

the code above demonstrates this, when onChange is called in the child, the props.visible ing from the parent will still be true, because the child ponent has it's own state. So the same thing will happen with your function. There is a way you can do this though, look at the code below:

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);
  }
}

if you want to just update the parent's dynamic function and only use it in the parent, you can just do what I did above, but if you want the child to be aware of when the dynamic function has changed, you'll need to move the dynamic function from the class into the state, this way, when you change the dynamic function, it will cause the child to re-render and it will get the newly set dynamic function passed down as a prop

本文标签: javascriptReact should i keep a function in local stateStack Overflow