1The `Output` element takes a single `output` prop and several child components and renders the appropriate components to render each output type.
2
3For example, we can create a `stream` output and use the `Output` and `StreamText` components needed for each output type.
4
5```jsx
6// Until we create <Stream />
7const { StreamText } = require("./stream-text");
8
9const output = Object.freeze({
10  output_type: "stream",
11  text: "Hello World\nHow are you?",
12  name: "stdout"
13});
14
15<Output output={output}>
16  <StreamText />
17</Output>;
18```
19
20Errors returned from the connected Jupyter kernel can be rendered.
21
22```jsx
23const { KernelOutputError } = require("./kernel-output-error");
24
25const output = Object.freeze({
26  output_type: "error",
27  ename: "NameError",
28  evalue: "Yikes!",
29  traceback: ["Yikes, never heard of that one!"]
30});
31
32<Output output={output}>
33  <KernelOutputError />
34</Output>;
35```
36
37The examples above are simple but we can use `Output` and our `Output`-related components to render even more complex structures. In the example below, we have an output that consists of a variety of output types such as stream and data display outputs. By passing the correct output and media types and passing their matching components as children, we can render a variety of outputs.
38
39```jsx
40const { RichMedia } = require("./rich-media");
41const { DisplayData } = require("./display-data");
42
43const { StreamText } = require("./stream-text");
44
45// Some "rich" handlers for Media
46const Plain = props => <marquee>{props.data}</marquee>;
47Plain.defaultProps = {
48  mediaType: "text/plain"
49};
50
51const HTML = props => <div dangerouslySetInnerHTML={{ __html: props.data }} />;
52HTML.defaultProps = {
53  mediaType: "text/html"
54};
55
56const outputs = [
57  {
58    output_type: "stream",
59    text: "Hello World\nHow are you?",
60    name: "stdout"
61  },
62  {
63    output_type: "display_data",
64    data: {
65      "text/plain": "O____O"
66    },
67    metadata: {}
68  },
69  {
70    output_type: "display_data",
71    data: {
72      "text/html": "<p>This is some HTML.</p>"
73    },
74    metadata: {}
75  },
76  {
77    output_type: "stream",
78    text: "Pretty good I would say",
79    name: "stdout"
80  }
81];
82
83<div>
84  {outputs.map((output, index) => (
85    <Output output={output} key={index}>
86      <StreamText />
87      <DisplayData>
88        <Plain />
89        <HTML />
90      </DisplayData>
91    </Output>
92  ))}
93</div>;
94```
95
96This structure also allows you to create your own components to override how a given output type is rendered. Below is an example that overrides the component to support `display_data` output types with a component that always renders the same thing.
97
98```jsx
99const { StreamText } = require("./stream-text");
100
101// Our own DisplayData component
102const MyDisplayData = props => (
103  <p>
104    <b>MyDisplayData.</b>
105  </p>
106);
107MyDisplayData.defaultProps = {
108  output_type: "display_data"
109};
110
111// Some "rich" handlers for Media. These aren't going to be
112// used becuase our custom MyDisplayData component doesn't do anything
113// with its child components.
114const Plain = props => <marquee>{props.data}</marquee>;
115Plain.defaultProps = {
116  mediaType: "text/plain"
117};
118
119const HTML = props => <div dangerouslySetInnerHTML={{ __html: props.data }} />;
120HTML.defaultProps = {
121  mediaType: "text/html"
122};
123
124const outputs = [
125  {
126    output_type: "display_data",
127    data: {
128      "text/plain": "O____O"
129    },
130    metadata: {}
131  },
132  {
133    output_type: "display_data",
134    data: {
135      "text/html": "<p>This is some HTML.</p>"
136    },
137    metadata: {}
138  }
139];
140
141<div>
142  {outputs.map((output, index) => (
143    <Output output={output} key={index}>
144      <MyDisplayData>
145        <Plain />
146        <HTML />
147      </MyDisplayData>
148    </Output>
149  ))}
150</div>;
151```
152
153If your app handles both `display_data` and `execute_result` output types in
154the same manner, you can pass an `output_type` array instead of a string.
155
156```jsx
157const Media = require("./media/");
158const { RichMedia } = require("./rich-media");
159const DisplayData = require("./display-data");
160
161// Our custom DisplayData/ExecuteResult component
162function CompositeOutput(props) {
163  const { output, children } = props;
164
165  return (
166    <RichMedia data={output.data} metadata={output.metadata}>
167      {children}
168    </RichMedia>
169  );
170}
171CompositeOutput.defaultProps = {
172  output: null,
173  output_type: ["display_data", "execute_result"]
174};
175
176const displayOutput = {
177  output_type: "display_data",
178  data: {
179    "text/html":
180      "<p>This is a <code>display_data</code> HTML output that <b>WILL</b> render</p>",
181    "text/plain": "This is some plain text that WILL NOT render"
182  }
183};
184
185const executeResultOutput = {
186  output_type: "execute_result",
187  data: {
188    "text/html":
189      "<p>This is an <code>execute_result</code> HTML output that <b>WILL</b> render</p>",
190    "text/plain": "This is some plain text that WILL NOT render"
191  }
192};
193
194// Try replacing `executeResultOutput` with `displayOutput`
195// both output_type will render as expected
196<Output output={executeResultOutput}>
197  <CompositeOutput>
198    <Media.Json />
199    <Media.HTML />
200    <Media.Plain />
201  </CompositeOutput>
202</Output>;
203```
204