简体   繁体   中英

How to change props of leaf node in a react elements tree

Say I got a elements tree like this:

<Form>
  <FormItem>
     <Input></Input>
  </FormItem>
  <Input></Input>
  <MyInput></MyInput>
</Form>

I want to disable all the Input and MyInput components.

Instead of adding {disabled: true} to all these Input components, I want to traverse and add disabled prop automaticly. So when I remove or add Input Component I should not concern the disabled prop.

First of all you need to define a state in the parent component, corresponding to the disabled attribute of your input components, let's call it this.state.isInputDisabled . So having that, you can pass it as a prop :

<Form>
  <FormItem>
     <Input isDisabled={this.state.isInputDisabled}></Input>
  </FormItem>
  <Input isDisabled={this.state.isInputDisabled}></Input>
  <MyInput isDisabled={this.state.isInputDisabled}></MyInput>
</Form>

And then when you change the state in the parent component, you also need to update children. To to that override componentWillReceiveProps method, for example:

class MyInput extends React.Component {

  componentWillReceiveProps(nextProps) {
    this.forceUpdate();
  }

  render() {
    return <input type="text" disabled={this.props.isDisabled} />
  }
}

To answer your comment:

What piece of code do you actually expect to handle the disabled attribute for you? There are two other ways to manage the children state from the parent I can think of:

  1. Store the references to input components in refs and manage them in the parent (but again this involves an additional prop you want to avoid).

  2. Grant a specific HTML class for rendered components and just use vanilla JS to update the disabled prop:

     function toggleInputDisabled(disable) { document .getElementsByClassName('your-input-class') .forEach(elem => elem.disabled = disable); } 

    Using vanilla JS is not forbidden in React, however it is considered a bad practice and you should go for it only if you see no simple way out.

Passing props down is the React way, however if you absolutely insist that you don't want to do that, there are a couple of options that spring to mind:

Use some kind of state container eg Redux

You can centrally manage the isInputDisabled flag in Redux state via Actions and Reducers. Then you wire each of your Input and MyInput components into your Redux state via react-redux . When the Redux state changes, all components wired into it via react-redux will be notified and render accordingly.

These two video tutorials from Dan Abramov (the co-creator of Redux) are a great introduction and advanced guide:

Use React Context

This is considered a more advanced feature and is discouraged by the React team where avoidable. It does become a bit "magic" and I personally don't like it as you no longer have the transparency of what props a component takes. From the context docs:

The vast majority of applications do not need to use context.

If you want your application to be stable, don't use context. It is an experimental API and it is likely to break in future releases of React.

If you aren't familiar with state management libraries like Redux or MobX, don't use context. For many practical applications, these libraries and their React bindings are a good choice for managing state that is relevant to many components. It is far more likely that Redux is the right solution to your problem than that context is the right solution.

If you aren't an experienced React developer, don't use context. There is usually a better way to implement functionality just using props and state.

If you insist on using context despite these warnings, try to isolate your use of context to a small area and avoid using the context API directly when possible so that it's easier to upgrade when the API changes.


Neither of the provided answers are what OP is looking for, which is clear here:

I want to traverse and add disabled prop automatically

To traverse the children of a React component, check out this.props.children and the React.Children helpers. You might be able to make a container component that iterates its children recursively, modifying the leaf nodes (those without children) to add the disabled prop.

For an example, check out https://mxstbr.blog/2017/02/react-children-deepdive/#manipulating-children .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM