Home > OS >  Variable prop preferredSize of allotment does not work
Variable prop preferredSize of allotment does not work

Time:12-27

I would like to make a draggable split panel for an editor. Its behavior is mainly like Console panel of CodeSandbox:

  1. When we click on Console, the panel is expanded, and the arrow becomes ArrowDown for closing.
  2. The border of the panel is dragabble.
  3. When we click on Console on an expanded panel, the panel is closed, and the arrow becomes ArrowUp for expanding.

I have the following code (https://codesandbox.io/s/reset-forked-ydhy97?file=/src/App.js:0-927) by https://github.com/johnwalley/allotment. The problem is that the prop preferredSize does not change following this.state.toExpand.

Does anyone know why this does not work?

import React from "react";
import { Allotment } from "allotment";
import "allotment/dist/style.css";
import styles from "./App.module.css";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      toExpand: true
    };
  }

  render() {
    return (
      <div>
        <div className={styles.container}>
          <Allotment vertical>
            <Allotment.Pane>Main Area</Allotment.Pane>
            <Allotment.Pane preferredSize={this.state.toExpand ? "0%" : "50%"}>
              <div
                onClick={() => {
                  this.setState({ toExpand: !this.state.toExpand });
                }}
              >
                Console &nbsp;
                {this.state.toExpand ? "ArrowUp" : "ArrowDown"}
              </div>
            </Allotment.Pane>
          </Allotment>
        </div>
      </div>
    );
  }
}

CodePudding user response:

The problem is that the prop preferredSize does not change following this.state.toExpand.

This is not the problem, it does change, however, the documentation states:

Allotment will attempt to use this size when adding this pane (including on initial mount) as well as when a user double clicks a sash, or the reset method is called on the Allotment instance.

It is not configured to update when the prop is changed, however, if you double click on the border after setting it to ArrowDown, it will reset to 50%.

Instead, if you add a reference to the Allotment element by first initializing a reference in the constructor:

constructor(props) {
  super(props);

  this.allotment = React.createRef();

  this.state = {
    toExpand: true
  };
}

And assigning it as a prop:

<Allotment vertical ref={this.allotment}>

Then you can add a callback to the setState for when you change the expand option that calls the reset function:

resetAllotment() {
  if (this.allotment.current) {
    this.allotment.current.reset();
  }
}
// ...
this.setState({ toExpand: !this.state.toExpand }, () => this.resetAllotment());

Side-note, it appears that the Allotment component does not have time to process the new prop change, before reset is called in the setState callback... which is illogical to me, however, you can work around this by a hacky setTimeout of 0ms:

resetAllotment() {
  setTimeout(() => this.allotment.current && this.allotment.current.reset(), 0);
}
  • Related