Реакция - изменение нескольких отдельных компонентов через один другой компонент с помощью API контекста - PullRequest
1 голос
/ 24 октября 2019

Допустим, у меня есть три компонента: App, Block и BlockOptions.

App имеет массив с именем blocks, который содержит все компоненты блока. Эти блоки отображаются внутри какого-то артборда. Поскольку каждый блок может быть изменен, я хочу, чтобы BlockOptions действовал как панель свойств всякий раз, когда выбран Block. Это Block должно быть возможно изменить оттуда. Помните, что BlockOptions находится в совершенно другом месте.

App.js:

class App extends Component {
  constructor(props) {
    super(props)

    this.state = {
      artboardSize: {
        width: 300,
        height: 200
      },
      blocks: []
    }
  }
  // App component contains several methods that change the blocks array, like this one
  addBlock(width, height) {
    const newBlock = {
      width: width,
      height: height
    }

    this.setState(prevState => ({
      blocks: [...prevState.blocks, newBlock]
    }));
  }
  render() {
    return (
      <GlobalContext.Provider value={this}>
        <div className="app">
          <Artboard /> // Where all Blocks go
          <Sidebar /> // Where BlockInfo goes
        </div>
      </GlobalContext.Provider>
    )
  }
}

Как видно выше, я использую Context API для предоставления всем компонентам доступа к Appсостояние и методы. Так, например, если щелкнуть кнопку где-то на странице, этот компонент вызывает метод App addBlock() для создания нового блока.

Вот как я сейчас рендеринг каждого блока вArtboard:

{context.state.blocks.map((block, key) => (
  <Block key={key} width={block.width * context.scale} height={block.height * context.scale} />
))}

В Block.js я хочу изменить массив блоков App с selected на true, когда пользователь нажимает на блок:

class Block extends Component {
  constructor(props) {
    super(props);

    this.state = {
      width: this.props.width,
      height: this.props.height,
      selected: false
      // etc...
    }
  }
  handleOnClick() {
    this.setState({
      selected: true
    });

    // But how do I update this in App?
  }
  render() {
    return (
      <div className="block" onClick={() => this.handleOnClick()}></div>
    )
  }
}

Но я не могу. Я могу обновить состояние в пределах Block, но не во всем самом приложении. Как мне это сделать?

Я довольно новичок в React. Поэтому, возможно, использование Context API не подходит, я действительно не знаю. Может быть, все мое мышление испорчено. Может быть, есть лучший способ справиться с этим?

В основном то, что я пытаюсь сделать: У меня есть набор компонентов, каждый из которых отличается друг от друга, чтобы можно было заменить некоторыевид «Панель настроек». Каждый блок отличается, поэтому эта панель должна меняться в зависимости от состояния выбранного блока.

1 Ответ

0 голосов
/ 24 октября 2019

Если вы решите использовать контекст, редуктор или состояние, вам нужно будет передать функцию в компонент блока, которая будет вызываться компонентом верхнего уровня, чтобы обновить значение и передать его дочерним элементам.

Если вы хотите использовать контекст, вы можете изменить значение на:

<GlobalContext.Provider value={{ blocks: this.state.blocks, addBlock: this.addBlock }} >

Таким образом, любой потребитель контекста имеет не только доступ к блокам, но и функцию для вызова для обновления. их для любых других потребителей в приложении.

{context.blocks.map((block, key) => <Block ... onAdd={context.addBlock} />)}

И в пределах блока:

handleOnClick() {
  this.setState ...
  this.props.onAdd();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...