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